Merge remote-tracking branch 'origin/0.11.0'
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..dde2dba
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,9 @@
+# TODO: Use eslint on js lib and generated code
+
+# Ignore lib/js for now, which uses jshint currently
+lib/js/*
+# Ignore all generated code for now
+**/gen-*
+
+# Don't lint nested node_modules
+**/node_modules
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..0aae820
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,24 @@
+{
+  "env": {
+    "es6": true,
+    "node": true
+  },
+  "extends": [
+    "eslint:recommended",
+    "plugin:prettier/recommended"
+  ],
+  "parserOptions": {
+    "ecmaVersion": 2017
+  },
+  "rules": {
+    "no-console": "off",
+    "no-var": "error",
+    "prefer-const": "error",
+    "no-constant-condition": [
+      "error",
+      {
+        "checkLoops": false
+      }
+    ]
+  }
+}
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 0000000..12d4afb
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,59 @@
+# Configuration for probot-stale - https://github.com/probot/stale
+
+# Number of days of inactivity before an Issue or Pull Request becomes stale
+daysUntilStale: 60
+
+# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
+# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
+daysUntilClose: 7
+
+# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
+exemptLabels:
+  - Do Not Merge
+  - blocked
+  - pinned
+  - security
+  - "[Status] Maybe Later"
+
+# Set to true to ignore issues in a project (defaults to false)
+exemptProjects: false
+
+# Set to true to ignore issues in a milestone (defaults to false)
+exemptMilestones: false
+
+# Label to use when marking as stale
+staleLabel: wontfix
+
+# Comment to post when marking as stale. Set to `false` to disable
+markComment: >
+  This issue has been automatically marked as stale because it has not had
+  recent activity. It will be closed in 7 days if no further activity occurs.
+  Thank you for your contributions.
+
+# Comment to post when removing the stale label.
+unmarkComment: >
+  This issue is no longer stale.
+  Thank you for your contributions.
+
+# Comment to post when closing a stale Issue or Pull Request.
+closeComment: >
+  This issue has been automatically closed due to inactivity.
+  Thank you for your contributions.
+
+# Limit the number of actions per hour, from 1-30. Default is 30
+limitPerRun: 30
+
+# Limit to only `issues` or `pulls`
+# only: issues
+
+# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
+# pulls:
+#   daysUntilStale: 30
+#   markComment: >
+#     This pull request has been automatically marked as stale because it has not had
+#     recent activity. It will be closed if no further activity occurs. Thank you
+#     for your contributions.
+
+# issues:
+#   exemptLabels:
+#     - confirmed
diff --git a/.gitignore b/.gitignore
index 8f1879e..b3a5920 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,28 +24,38 @@
 tags
 
 .*project
+.classpath
+.dub
+.settings
+.checkstyle
 junit*.properties
 .idea
+*.iml
+*.ipr
+*.iws
 gen-*
 Makefile
 Makefile.in
 aclocal.m4
 acinclude.m4
+apache-thrift-test-library
 autom4te.cache
 cmake-*
+dub.selections.json
+libapache-thrift.a
 node_modules
 compile
 test-driver
 erl_crash.dump
-package-lock.json
 project.lock.json
 
 .sonar
 .DS_Store
 .svn
 .vagrant
+.vscode
+.vs
 
-/contrib/.vagrant/
 /aclocal/libtool.m4
 /aclocal/lt*.m4
 /autoscan.log
@@ -80,6 +90,7 @@
 /configure
 /configure.lineno
 /configure.scan
+/contrib/.vagrant/
 /contrib/fb303/config.cache
 /contrib/fb303/config.log
 /contrib/fb303/config.status
@@ -94,6 +105,13 @@
 /contrib/fb303/py/fb303/ttypes.py
 /depcomp
 /install-sh
+/lib/cl/backport-update.zip
+/lib/cl/lib
+/lib/cl/run-tests
+/lib/cl/quicklisp.lisp
+/lib/cl/externals/
+/lib/cl/run-tests
+/lib/cl/quicklisp/
 /lib/cpp/Debug/
 /lib/cpp/Debug-mt/
 /lib/cpp/Release/
@@ -112,8 +130,9 @@
 /lib/cpp/test/OptionalRequiredTest
 /lib/cpp/test/SecurityTest
 /lib/cpp/test/SpecializationTest
-/lib/cpp/test/ReflectionTest
 /lib/cpp/test/RecursiveTest
+/lib/cpp/test/ReflectionTest
+/lib/cpp/test/RenderedDoubleConstantsTest
 /lib/cpp/test/TFDTransportTest
 /lib/cpp/test/TFileTransportTest
 /lib/cpp/test/TInterruptTest
@@ -181,35 +200,14 @@
 /lib/dart/**/packages
 /lib/dart/**/.pub/
 /lib/dart/**/pubspec.lock
-/lib/delphi/src/*.dcu
-/lib/delphi/test/*.identcache
-/lib/delphi/test/*.local
-/lib/delphi/test/*.dcu
-/lib/delphi/test/*.2007
-/lib/delphi/test/*.dproj
-/lib/delphi/test/*.dproj
-/lib/delphi/test/codegen/*.bat
-/lib/delphi/test/skip/*.local
-/lib/delphi/test/skip/*.identcache
-/lib/delphi/test/skip/*.identcache
-/lib/delphi/test/skip/*.dproj
-/lib/delphi/test/skip/*.dproj
-/lib/delphi/test/skip/*.2007
-/lib/delphi/test/serializer/*.identcache
-/lib/delphi/test/serializer/*.dproj
-/lib/delphi/test/serializer/*.local
-/lib/delphi/test/serializer/*.2007
-/lib/delphi/test/serializer/*.dcu
-/lib/delphi/test/multiplexed/*.dproj
-/lib/delphi/test/multiplexed/*.2007
-/lib/delphi/test/multiplexed/*.local
-/lib/delphi/test/multiplexed/*.identcache
-/lib/delphi/test/multiplexed/*.dcu
-/lib/delphi/test/typeregistry/*.2007
-/lib/delphi/test/typeregistry/*.dproj
-/lib/delphi/test/typeregistry/*.identcache
-/lib/delphi/test/typeregistry/*.local
-/lib/delphi/test/typeregistry/*.dcu
+/lib/delphi/test/skip/*.request
+/lib/delphi/test/skip/*.response
+/lib/delphi/**/*.identcache
+/lib/delphi/**/*.local
+/lib/delphi/**/*.dcu
+/lib/delphi/**/*.2007
+/lib/delphi/**/*.dproj
+/lib/delphi/**/codegen/*.bat
 /lib/erl/.eunit
 /lib/erl/.generated
 /lib/erl/.rebar/
@@ -220,16 +218,17 @@
 /lib/erl/test/*.hrl
 /lib/erl/test/Thrift_omit_without.thrift
 /lib/haxe/test/bin
+/lib/haxe/test/data.tmp
 /lib/hs/dist
+/lib/java/.gradle
+/lib/java/android/.gradle
 /lib/java/build
+/lib/java/target
 /lib/js/dist
 /lib/js/doc
-/lib/js/package-lock.json
 /lib/js/test/build
-/lib/netcore/**/.vs
 /lib/netcore/**/bin
 /lib/netcore/**/obj
-/lib/netcore/**/gen-*
 /lib/nodejs/coverage
 /lib/nodejs/node_modules/
 /lib/perl/MANIFEST
@@ -253,6 +252,7 @@
 /lib/php/src/ext/thrift_protocol/build/
 /lib/php/src/ext/thrift_protocol/config.*
 /lib/php/src/ext/thrift_protocol/configure
+/lib/php/src/ext/thrift_protocol/configure.ac
 /lib/php/src/ext/thrift_protocol/configure.in
 /lib/php/src/ext/thrift_protocol/install-sh
 /lib/php/src/ext/thrift_protocol/libtool
@@ -285,19 +285,26 @@
 /lib/rs/test/src/ultimate.rs
 /lib/rs/*.iml
 /lib/rs/**/*.iml
+/lib/swift/.build
 /libtool
 /ltmain.sh
 /missing
 /node_modules/
+/vendor/
+/composer.lock
 /stamp-h1
 /test/features/results.json
 /test/results.json
 /test/c_glib/test_client
 /test/c_glib/test_server
+/test/cl/TestServer
+/test/cl/TestClient
 /test/cpp/StressTest
 /test/cpp/StressTestNonBlocking
 /test/cpp/TestClient
 /test/cpp/TestServer
+/test/csharp/obj
+/test/csharp/bin
 /test/dart/**/.packages
 /test/dart/**/packages
 /test/dart/**/.pub/
@@ -323,10 +330,8 @@
 /test/php/php_ext_dir/
 /test/py.twisted/_trial_temp/
 /test/rb/Gemfile.lock
-/test/netcore/**/.vs
 /test/netcore/**/bin
 /test/netcore/**/obj
-/test/netcore/**/gen-*
 /test/netcore/Thrift
 /test/php/php_ext_dir/
 /test/rs/Cargo.lock
@@ -335,6 +340,17 @@
 /test/rs/target/
 /test/rs/*.iml
 /test/rs/**/*.iml
+/lib/cl/backport-update.zip
+/lib/cl/lib
+/tutorial/cl/quicklisp.lisp
+/tutorial/cl/externals/
+/tutorial/cl/quicklisp/
+/tutorial/cl/TutorialClient
+/tutorial/cl/TutorialServer
+/tutorial/cl/backport-update.zip
+/tutorial/cl/lib/
+/tutorial/cl/shared-implementation.fasl
+/tutorial/cl/tutorial-implementation.fasl
 /tutorial/cpp/TutorialClient
 /tutorial/cpp/TutorialServer
 /tutorial/c_glib/tutorial_client
@@ -350,15 +366,12 @@
 /tutorial/dart/**/packages
 /tutorial/dart/**/.pub/
 /tutorial/dart/**/pubspec.lock
-/tutorial/delphi/*.dsk
-/tutorial/delphi/*.local
-/tutorial/delphi/*.tvsconfig
-/tutorial/delphi/DelphiClient/dcu
-/tutorial/delphi/DelphiServer/dcu
-/tutorial/delphi/DelphiClient/*.local
-/tutorial/delphi/DelphiClient/*.identcache
-/tutorial/delphi/DelphiServer/*.identcache
-/tutorial/delphi/DelphiServer/*.local
+/tutorial/delphi/**/*.dsk
+/tutorial/delphi/**/*.local
+/tutorial/delphi/**/*.tvsconfig
+/tutorial/delphi/**/dcu
+/tutorial/delphi/**/*.local
+/tutorial/delphi/**/*.identcache
 /tutorial/go/gopath
 /tutorial/go/go-tutorial
 /tutorial/go/calculator-remote
@@ -370,10 +383,8 @@
 /tutorial/hs/dist/
 /tutorial/java/build/
 /tutorial/js/build/
-/tutorial/netcore/**/.vs
 /tutorial/netcore/**/bin
 /tutorial/netcore/**/obj
-/tutorial/netcore/**/gen-*
 /tutorial/netcore/Thrift
 /tutorial/rs/*.iml
 /tutorial/rs/src/shared.rs
@@ -382,3 +393,4 @@
 /tutorial/rs/target
 /tutorial/rs/Cargo.lock
 /ylwrap
+
diff --git a/.rustfmt.toml b/.rustfmt.toml
index 2962d47..dca5afd 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -1,7 +1,64 @@
 max_width = 100
-fn_args_layout = "Block"
-array_layout = "Block"
-where_style = "Rfc"
-generics_indent = "Block"
-fn_call_style = "Block"
-reorder_imported_names = true
+hard_tabs = false
+tab_spaces = 4
+newline_style = "Auto"
+use_small_heuristics = "Default"
+indent_style = "Block"
+wrap_comments = false
+format_doc_comments = false
+comment_width = 80
+normalize_comments = false
+normalize_doc_attributes = false
+license_template_path = ""
+format_strings = false
+format_macro_matchers = false
+format_macro_bodies = true
+empty_item_single_line = true
+struct_lit_single_line = true
+fn_single_line = false
+where_single_line = false
+imports_indent = "Block"
+imports_layout = "Mixed"
+merge_imports = false
+reorder_imports = true
+reorder_modules = true
+reorder_impl_items = false
+type_punctuation_density = "Wide"
+space_before_colon = false
+space_after_colon = true
+spaces_around_ranges = false
+binop_separator = "Front"
+remove_nested_parens = true
+combine_control_expr = true
+overflow_delimited_expr = false
+struct_field_align_threshold = 0
+enum_discrim_align_threshold = 0
+match_arm_blocks = true
+force_multiline_blocks = false
+fn_args_density = "Tall"
+brace_style = "SameLineWhere"
+control_brace_style = "AlwaysSameLine"
+trailing_semicolon = true
+trailing_comma = "Vertical"
+match_block_trailing_comma = false
+blank_lines_upper_bound = 1
+blank_lines_lower_bound = 0
+edition = "2015"
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true
+condense_wildcard_suffixes = false
+color = "Auto"
+required_version = "1.0.0"
+unstable_features = false
+disable_all_formatting = false
+skip_children = false
+hide_parse_errors = false
+error_on_line_overflow = false
+error_on_unformatted = false
+report_todo = "Never"
+report_fixme = "Never"
+ignore = []
+emit_mode = "Files"
+make_backup = false
diff --git a/.travis.yml b/.travis.yml
index 9a94e36..637b5d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,6 @@
   - if [[ `uname` == "Linux" ]]; then build/docker/refresh.sh; fi
 
 stages:
-# - osx       # up front for now (for testing)
   - docker    # docker images
   - thrift    # thrift build jobs
 
@@ -43,8 +42,8 @@
   global:
     - SCRIPT="cmake.sh"
     - BUILD_ARG=""
-    - BUILD_ENV="-e CC=clang -e CXX=clang++"
-    - DISTRO=ubuntu-xenial
+    - BUILD_ENV="-e CC=gcc -e CXX=g++ -e THRIFT_CROSSTEST_CONCURRENCY=4"
+    - DISTRO=ubuntu-bionic
     - BUILD_LIBS="CPP C_GLIB HASKELL JAVA PYTHON TESTING TUTORIALS"  # only meaningful for CMake builds
     - TRAVIS_BUILD_STAGE=test
     # DOCKER_REPO (this works for all builds as a source for docker images - you can override for fork builds in your Travis settings)
@@ -54,28 +53,17 @@
 
 jobs:
   include:
-    # ------------------------- phase: osx --------------------------
-    # - stage: osx
-    #   os: osx
-    #   osx_image: xcode9
-    #   script: build/docker/scripts/autotools.sh
-
     # ========================= stage: docker =========================
     - stage: docker
       script: true
       env:
-        - JOB="Docker Build ubuntu-trusty 14.04"
-        - DISTRO=ubuntu-trusty
-        - TRAVIS_BUILD_STAGE=docker
-    - script: true
-      env:
-        - JOB="Docker Build ubuntu-xenial 16.04"
+        - JOB="Docker Build ubuntu-xenial 16.04 LTS"
         - DISTRO=ubuntu-xenial
         - TRAVIS_BUILD_STAGE=docker
     - script: true
       env:
-        - JOB="Docker Build ubuntu-artful 17.10"
-        - DISTRO=ubuntu-artful
+        - JOB="Docker Build ubuntu-bionic 18.04 LTS"
+        - DISTRO=ubuntu-bionic
         - TRAVIS_BUILD_STAGE=docker
 
     # ========================= stage: thrift =======================
@@ -87,8 +75,6 @@
       env:
         - JOB="Cross Language Tests"
         - SCRIPT="cross-test.sh"
-        - BUILD_ARG=""
-        - BUILD_ENV="-e CC=clang -e CXX=clang++ -e THRIFT_CROSSTEST_CONCURRENCY=4"
 
     # fork based PR builds cannot exceed 50 minutes per job
     - stage: thrift
@@ -98,7 +84,6 @@
         - JOB="Cross Language Tests (Binary Protocol)"
         - SCRIPT="cross-test.sh"
         - BUILD_ARG="-'(binary)'"
-        - BUILD_ENV="-e CC=clang -e CXX=clang++ -e THRIFT_CROSSTEST_CONCURRENCY=4"
 
     - stage: thrift
       script: build/docker/run.sh
@@ -107,7 +92,6 @@
         - JOB="Cross Language Tests (Header, JSON Protocols)"
         - SCRIPT="cross-test.sh"
         - BUILD_ARG="-'(header|json)'"
-        - BUILD_ENV="-e CC=clang -e CXX=clang++ -e THRIFT_CROSSTEST_CONCURRENCY=4"
 
     - stage: thrift
       script: build/docker/run.sh
@@ -116,7 +100,6 @@
         - JOB="Cross Language Tests (Compact and Multiplexed Protocols)"
         - SCRIPT="cross-test.sh"
         - BUILD_ARG="-'(compact|multiplexed)'"
-        - BUILD_ENV="-e CC=clang -e CXX=clang++ -e THRIFT_CROSSTEST_CONCURRENCY=4"
 
     # ------------------------- phase: sca --------------------------
     # QA jobs for code analytics and metrics
@@ -125,7 +108,6 @@
       env:
         - JOB="Static Code Analysis"
         - SCRIPT="sca.sh"
-        - DISTRO=ubuntu-artful
 
     # C and C++ undefined behavior.
     # A binary crashes if undefined behavior occurs and produces a stack trace.
@@ -134,63 +116,58 @@
       env:
         - JOB="UBSan"
         - SCRIPT="ubsan.sh"
-        - DISTRO=ubuntu-artful
         - BUILD_ARG="--without-python --without-py3"
 
+    # ------------------------- phase: autotools --------------------
+    # TODO: Remove them once migrated to CMake
+    - script: build/docker/run.sh
+      env:
+        - JOB="Autotools (Ubuntu Bionic)"
+        - SCRIPT="autotools.sh"
+
+    - script: build/docker/run.sh
+      env:
+        - JOB="Autotools (Ubuntu Xenial)"
+        - DISTRO=ubuntu-xenial
+        - SCRIPT="autotools.sh"
+
     # ------------------------- phase: cmake ------------------------
     - script: build/docker/run.sh
       env:
-        - JOB="CMake (Ubuntu Xenial)"
+        - JOB="CMake"
 
     # C++ specific options: compiler plug-in, threading model
     - script: build/docker/run.sh
       env:
-        - JOB="C++98 (Boost Thread)"
-        - SCRIPT="cmake.sh"
-        - BUILD_LIBS="CPP TESTING TUTORIALS"
-        - BUILD_ARG="-DCMAKE_CXX_STANDARD=98 -DCMAKE_CXX_STANDARD_REQUIRED=ON -DCMAKE_CXX_EXTENSIONS=OFF --DWITH_BOOSTTHREADS=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF"
-        - BUILD_ENV=""
-
-    - script: build/docker/run.sh
-      env:
         - JOB="C++ (Std Thread) and Plugin"
         - SCRIPT="cmake.sh"
         - BUILD_LIBS="CPP TESTING TUTORIALS"
         - BUILD_ARG="-DWITH_PLUGIN=ON -DWITH_STDTHREADS=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF"
         - BUILD_ENV="-e CC=clang -e CXX=clang++"
 
-    # ------------------------- phase: autotools --------------------
-    # TODO: Remove them once migrated to CMake
-    - script: build/docker/run.sh
-      env:
-        - JOB="Autotools (Ubuntu Artful)"
-        - DISTRO=ubuntu-artful
-        - SCRIPT="autotools.sh"
-        - BUILD_ENV="-e CC=gcc -e CXX=g++"
-
-    - script: build/docker/run.sh
-      env:
-        - JOB="Autotools (Ubuntu Xenial)"
-        - DISTRO=ubuntu-xenial
-        - SCRIPT="autotools.sh"
-        - BUILD_ENV="-e CC=gcc -e CXX=g++"
-
-    - script: build/docker/run.sh
-      env:
-        - JOB="Autotools (Ubuntu Trusty)"
-        - DISTRO=ubuntu-trusty
-        - SCRIPT="autotools.sh"
-        - BUILD_ENV="-e CC=gcc -e CXX=g++"
-
     # ------------------------- phase: dist -------------------------
     - script: build/docker/run.sh
       env:
         - JOB="make dist"
         - SCRIPT="make-dist.sh"
-        - BUILD_ENV="-e CC=gcc -e CXX=g++"
 
     - script: build/docker/run.sh
       env:
         - JOB="Debian Packages"
         - SCRIPT="dpkg.sh"
-        - BUILD_ENV="-e CC=gcc -e CXX=g++"
+
+    # ------------------------- phase: coverity ---------------------
+    # We build the coverity scan build once monthly using a travis cron job
+    - if: (env(COVERITY_SCAN_NOTIFICATION_EMAIL) IS present) AND (branch IN (master)) AND (type IN (cron))
+      script: build/docker/run.sh
+      env:
+        - JOB="Coverity Scan"
+        - SCRIPT="covscan.sh"
+     
+
+  ### ------------------------- phase: osx --------------------------
+  # disabled due to the time delays it imposes on build jobs
+  # - os: osx
+  #   osx_image: xcode9
+  #   script: build/docker/scripts/autotools.sh
+
diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec
new file mode 100644
index 0000000..54ed2c6
--- /dev/null
+++ b/ApacheThrift.nuspec
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+
+<!--
+  Licensed 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.
+
+  Instructions for building a nuget package:
+
+  1. Open Thrift.sln in lib\csharp\src and build the release version
+     of the "Thrift" and "Thrift.45" projects.
+  2. Open Thrift.sln in lib\netcore and build the release version of
+     the "Thrift" project.
+  3. nuget setApiKey <your-api-key>
+  3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg
+  4. nuget push ApacheThrift.1.0.0.nupkg -Source https://api.nuget.org/v3/index.json
+  -->
+
+<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
+  <metadata>
+    <id>ApacheThrift</id>
+    <version>1.0.0</version>
+    <title>Apache Thrift 1.0.0</title>
+    <authors>Apache Thrift Developers</authors>
+    <owners>Apache Software Foundation</owners>
+    <license type="expression">Apache-2.0</license>
+    <projectUrl>http://thrift.apache.org/</projectUrl>
+    <requireLicenseAcceptance>true</requireLicenseAcceptance>
+    <summary>Apache Thrift .NET Library</summary>
+    <description>
+      Contains runtime libraries from lib/csharp for net35 and net45 frameworks, 
+      and from lib/netcore for netstandard2.0 framework development.
+    </description>
+    <repository type="GitHub" url="https://github.com/apache/thrift" branch="release/1.0.0" />
+    <tags>Apache Thrift RPC</tags>
+  </metadata>
+  <files>
+    <file src="lib\csharp\src\bin\Release\Thrift.*" target="lib\net35" />
+    <file src="lib\csharp\src\bin\Release\Thrift45.*" target="lib\net45" />
+    <file src="lib\netcore\Thrift\bin\Release\netstandard2.0\*.*" target="lib\netstandard2.0" />
+  </files>
+</package>
\ No newline at end of file
diff --git a/CHANGES b/CHANGES
index 4009f26..244f0da 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,266 @@
 Apache Thrift Changelog
 
+================================================================================
+Thrift 0.12.0
+--------------------------------------------------------------------------------
+## New Languages
+    * Common LISP (cl)
+    * Swift
+    * Typescript (nodets)
+
+## Deprecated Languages
+    * Cocoa
+
+## Breaking Changes (since 0.11.0)
+    * [THRIFT-4529] - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions
+    * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped.
+    * [THRIFT-4474] - PHP now uses the PSR-4 loader by default instead of class maps.
+    * [THRIFT-4532] - method signatures changed in the compiler's t_oop_generator.
+    * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved.
+
+## Known Issues (Blocker or Critical)
+    * [THRIFT-4037] - build: use a single build system for thrift
+    * [THRIFT-4119] - build: bootstrap.sh is missing from source tarball
+    * [THRIFT-3289] - csharp: socket exhaustion in csharp implementation
+    * [THRIFT-3029] - cocoa: Getters for fields defined with uppercase names do not work
+    * [THRIFT-3325] - cocoa: Extended services aren't subclasses in generated Cocoa
+    * [THRIFT-4116] - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa
+    * [THRIFT-3877] - cpp: the http implementation is not standard; interop with other languages is spotty at best
+    * [THRIFT-4180] - cpp: Impossible to build Thrift C++ library for Android (NDK)
+    * [THRIFT-4384] - cpp: Using multiple async services simultaneously is not thread-safe
+    * [THRIFT-3108] - haskell: Defaulted struct parameters on a service generates invalid Haskell
+    * [THRIFT-3990] - nodejs: Exception swallowed by deserialization function
+    * [THRIFT-4214] - nodejs: map<i64,value> key treated as hex value in JavaScript
+    * [THRIFT-4602] - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process'
+    * [THRIFT-4639] - nodejs: Sequence numbering for multiplexed protocol broken
+    * [THRIFT-1310] - php: sequence and reconnection management issues
+    * [THRIFT-1538] - php: Error during deserialization int64 on 32-bit architecture
+    * [THRIFT-1580] - php: thrift type i64 java to php serialize/deserealize not working
+    * [THRIFT-1950] - php: PHP gets stuck in infinite loop
+    * [THRIFT-2954] - python: sending int or float in a double field breaks the connection
+    * [THRIFT-4080] - python: unix sockets can get stuck forever
+    * [THRIFT-4281] - python: generated code is out of order and causes load issues
+    * [THRIFT-4677] - py3: UnicodeDecideError in Python3
+
+## Build Process
+    * [THRIFT-4067] - Windows thrift compiler distributed on the apache web site has runtime dependencies
+    * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang
+    * [THRIFT-4579] - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10)
+    * [THRIFT-4508] - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more
+    * [THRIFT-4397] - ubuntu install instructions broken on 16.04
+    * [THRIFT-4545] - Appveyor builds are failing due to a haskell / cabal update in chocolatey
+    * [THRIFT-4452] - optimize Dockerfile (only onetime apt-get update)
+    * [THRIFT-4440] - rm `build/docker/ubuntu-trusty/Dockerfile.orig`
+    * [THRIFT-4352] - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2
+    * [THRIFT-4666] - DLang Client Pool Test fails sporadically
+    * [THRIFT-4676] - CL tutorial build fails sporadically
+    * [THRIFT-4456] - Make haxelib download quiet so it doesn't blow up the build log
+    * [THRIFT-4605] - bootstrap.sh fails if automake=1.16.1
+
+## c_glib
+    * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved.
+    * [THRIFT-4622] - glibC compilation issue
+    * [THRIFT-4671] - c glib is unable to handle client close unexpectedly
+
+## cl (new language support in 0.12.0)
+    * [THRIFT-82] - Common Lisp support
+
+## csharp
+    * [THRIFT-4558] - reserved Csharp keywords are not escaped in some cases
+    * [THRIFT-4637] - C# async mode generates incorrect code with inherited services
+    * [THRIFT-4672] - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases
+    * [THRIFT-4539] - Allow TBufferedTransport to be used as base class
+    * [THRIFT-4535] - XML docs; code cleanup (tabs->spaces; String->string)
+    * [THRIFT-4492] - protected ExceptionType type member of TApplicationException cannot be accessed
+    * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding
+    * [THRIFT-4455] - Missing dispose calls in ThreadedServer & ThreadpoolServer
+    * [THRIFT-4609] - keep InnerException wherever appropriate
+    * [THRIFT-4673] - IAsyncResult not supported by layered transports (buffered/framed)
+
+## cpp
+    * [THRIFT-4476] - Typecasting problem on list items
+    * [THRIFT-4465] - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources)
+    * [THRIFT-4680] - TBufferTransports.h does not compile under Visual Studio 2017
+    * [THRIFT-4618] - TNonblockingServer crash because of limitation of select()
+    * [THRIFT-4620] - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer.
+    * [THRIFT-4571] - ZeroMQ contrib library needs a refresh
+    * [THRIFT-4559] - TSSLServerSocket incorrectly prints errors
+    * [THRIFT-4578] - Move `TAsyncProtocolProcessor` into main thrift library
+    * [THRIFT-4418] - evhttp_connection_new is deprecated; use evhttp_connection_base_new
+
+## compiler
+    * [THRIFT-4644] - Compiler cannot be compiled on macOS(maybe also on other platforms with clang)
+    * [THRIFT-4531] - Thrift generates wrong Python code for immutable structures with optional members
+    * [THRIFT-4513] - thrift generated code is not stable for constants
+    * [THRIFT-4532] - Avoid updating Thrift compiler generated code if the output has not changed
+    * [THRIFT-4400] - Visual Studio Compiler project should link runtime statically in release builds
+    * [THRIFT-4399] - plugin.thrift t_const_value is not used as a union in C++ code -- fix this
+    * [THRIFT-4496] - Dealing with language keywords in Thrift (e.g. service method names)
+    * [THRIFT-4393] - repeated runs of compiler produce different binary output at plugin interface
+
+## dlang
+    * [THRIFT-4478] - Thrift will not build with dlang 2.078 or later
+    * [THRIFT-4503] - dlang servers logError on normal client disconnection
+    * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang
+
+## dart
+    * [THRIFT-4646] - Effective Dart and Exceptions
+    * [THRIFT-4439] - Shouldn't download dart.deb directly.
+
+## delphi
+    * [THRIFT-4562] - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown
+    * [THRIFT-4554] - uncompileable code with member names that are also types under specific conditions
+    * [THRIFT-4422] - Add Async implementation via IFuture
+    * [THRIFT-4485] - Possible invalid ptr AV with overlapped read/write on pipes
+    * [THRIFT-4549] - Thrift exceptions should derive from TException
+    * [THRIFT-4540] - buffered transport broken when trying to re-open a formerly closed transport
+    * [THRIFT-4473] - Move Thrift.Console.pas out of the Library
+    * [THRIFT-4490] - Allow a default service as fallback for multiplex processors connected by old clients
+    * [THRIFT-4454] - Large writes/reads may cause range check errors in debug mode
+    * [THRIFT-4461] - Compiler directive should match Delphi XE4
+    * [THRIFT-4462] - First line in Console duplicated
+    * [THRIFT-4642] - FPU ctrl word settings may cause an unexpected "denormalized" error
+    * [THRIFT-4589] - HTTP client timeouts are a) incomplete and b) not used at all
+    * [THRIFT-4590] - running the test client using HTTP transport leads to "CoInitialize not called"
+
+## erlang
+    * [THRIFT-4497] - Erlang records should use map() for map type
+    * [THRIFT-4495] - Erlang records should allow 'undefined' for non-required fields
+    * [THRIFT-4580] - Fix erlang tutorial unpack on Windows
+    * [THRIFT-4582] - Ubuntu Xenial erlang 18.3 "make check" fails
+
+## golang
+    * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped.
+    * [THRIFT-4253] - Go generator assigns strings to field in const instead of pointers.
+    * [THRIFT-4573] - Unions Field Count Does Not Consider Binary
+    * [THRIFT-4447] - Golang: Panic on p.c.Call when using deprecated initializers
+    * [THRIFT-4650] - Required field incorrectly marked as set when fieldType does not match
+    * [THRIFT-4486] - Golang: -remote.go client cleanup
+    * [THRIFT-4537] - TSimpleServer can exit Accept loop with lock still acquired
+    * [THRIFT-4516] - Add support for go 1.10
+    * [THRIFT-4421] - golang tests rely on gomock, which has change behaviour, causing tests to fail
+    * [THRIFT-4626] - Communication crash when using binary/compact protocol and zlib transport
+    * [THRIFT-4659] - golang race detected when closing listener socket
+
+## haskell
+    * [THRIFT-4634] - Haskell builds with older cabal cannot reconcile complex version requirements
+
+## java
+    * [THRIFT-4259] - Thrift does not compile due to Ant Maven task errors
+    * [THRIFT-1418] - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element
+    * [THRIFT-4530] - proposal: add nullability annotations to generated Java code
+    * [THRIFT-4614] - Generate missing @Nullable annotations for Java iterator getters
+    * [THRIFT-4555] - Getter of binary field in Java creates unnecessary copy
+    * [THRIFT-3983] - libthrift is deployed on central with pom packaging instead of jar
+    * [THRIFT-4294] - Java Configure Fails for Ant >= 1.10
+    * [THRIFT-4178] - Java libraries missing from package when using cmake
+    * [THRIFT-4120] - pom files are not generated or provided in the build
+    * [THRIFT-1507] - Maven can't download resource from central when behind a proxy and won't use local repository
+    * [THRIFT-4556] - Optional rethrow of unhandled exceptions in java processor
+    * [THRIFT-4337] - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters
+    * [THRIFT-4566] - Pass message of unhandled exception to optional rethrow.
+    * [THRIFT-4506] - Remove assertion in Java SASL code that would be ignored in release builds
+    * [THRIFT-4470] - Include popular IDE file templates to gitignore
+    * [THRIFT-4429] - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization
+    * [THRIFT-3769] - Fix logic of THRIFT-2268
+    * [THRIFT-4494] - Increase Java Socket Buffer Size
+    * [THRIFT-4499] - Remove Magic Number In TFIleTransport
+
+## js
+    * [THRIFT-4406] - JavaScript: Use modern Promise implementations
+    * [THRIFT-4625] - let / const variable decorators for es6 compiler
+    * [THRIFT-4653] - ES6 Classes
+    * [THRIFT-4592] - JS: readI32 performance on large arrays is very poor in Chrome
+    * [THRIFT-4509] - js and nodejs libraries need to be refreshed with current libraries
+    * [THRIFT-4403] - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen
+    * [THRIFT-4436] - Deserialization of nested list discards content
+    * [THRIFT-4437] - JS WebSocket client callbacks invoked twice on parallel requests
+    * [THRIFT-4679] - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js
+    * [THRIFT-4551] - Add prettier for consistent JS code formatting
+
+## lua
+    * [THRIFT-4591] - lua client uses two write() calls per framed message send
+    * [THRIFT-3863] - Can't "make install" Lua Library
+
+## netcore
+    * [THRIFT-4524] - .NET Core Server doesn't close properly when cancelled
+    * [THRIFT-4434] - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process
+    * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding
+
+## node.js
+    * [THRIFT-4225] - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail
+    * [THRIFT-3950] - Memory leak while calling oneway method
+    * [THRIFT-3143] - add typescript directory support
+    * [THRIFT-4564] - TBufferedTransport can leave corrupt data in the buffer
+    * [THRIFT-4647] - Node.js Fileserver webroot path
+    * [THRIFT-4489] - Unix domain socket support for NodeJS client
+    * [THRIFT-4443] - node.js json_protocol throws error in skip function
+    * [THRIFT-4604] - NodeJS: Expose Int64 from browser.js for consumption by browser
+    * [THRIFT-4480] - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0
+
+## perl
+    * [THRIFT-4382] - Replace the use of Perl Indirect Object Syntax calls to new()
+    * [THRIFT-4471] - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module
+    * [THRIFT-4416] - Perl CPAN Packaging Improvements
+
+## php
+    * [THRIFT-4474] - PHP generator use PSR-4 default
+    * [THRIFT-4463] - PHP generated code match PSR-2
+    * [THRIFT-4373] - Extending Thrift class results in "Attempt serialize from non-Thrift object"
+    * [THRIFT-4354] - TSocket block on read
+    * [THRIFT-4423] - migrate php library to psr-4
+    * [THRIFT-4656] - infinite loop in latest PHP library
+    * [THRIFT-4477] - TBufferedTransport must have underlying transport
+    * [THRIFT-4475] - lib/php/test should be checked for PSR-2
+    * [THRIFT-4498] - add phpcs back
+    * [THRIFT-4460] - php library use PSR-2
+    * [THRIFT-4641] - TCurlClient doesn't check for HTTP status code
+    * [THRIFT-4645] - TCurlClient: show actual error message when throwing TTransportException
+    * [THRIFT-4674] - Add stream context support into PHP/THttpClient
+    * [THRIFT-4459] - reduce php library directory depth
+
+## python
+    * [THRIFT-4670] - Twisted, slots, and void method fails with "object has no attribute 'success'"
+    * [THRIFT-4464] - Potentially server-crashing typo in Python TNonblockingServer
+    * [THRIFT-4548] - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python
+    * [THRIFT-4577] - Outdated cipher string in python unit test
+    * [THRIFT-4505] - python build on Vagrant Windows boxes fails
+    * [THRIFT-4621] - THeader for Python
+    * [THRIFT-4668] - make socket backlog configurable for python
+    * [THRIFT-4561] - Python: cleanup socket timeout settings
+
+## ruby
+    * [THRIFT-4289] - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation
+    * [THRIFT-4342] - Support ruby rspec 3
+    * [THRIFT-4525] - Add ssl socket option to ruby cross tests
+    * [THRIFT-4450] - Add seek support to TCompactInputProtocol in Rust
+    * [THRIFT-4631] - Codegen Creates Invalid Ruby for Recursive Structs
+    * [THRIFT-4472] - Fix the genspec for ruby so it does not complain about an invalid license
+
+## rust
+    * [THRIFT-4662] - Rust const string calls function at compile time
+    * [THRIFT-4661] - Rust enum name wrong case in generated structs
+    * [THRIFT-4617] - Avoid generating conflicting struct names in Rust code
+    * [THRIFT-4529] - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines
+    * [THRIFT-4390] - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes
+    * [THRIFT-4419] - Rust framed transport cannot handle writes above 4096 bytes
+    * [THRIFT-4658] - Rust's TBinaryInputProtocol fails when strict is false
+    * [THRIFT-4187] - Dart -> Rust Framed cross tests fail
+    * [THRIFT-4664] - Rust cannot create ReadHalf/WriteHalf to implement custom tranports
+    * [THRIFT-4665] - Keep Rust library up-to-date on crates.io
+
+## swift (new language support in 0.12.0)
+    * [THRIFT-3773] - Swift Library
+
+## test suite
+    * [THRIFT-4515] - Gracefully shutdown cross-test servers to fully test teardown
+    * [THRIFT-4085] - Add .NET Core to the make cross standard test suite
+    * [THRIFT-4358] - Add unix domain sockets in ruby to cross test - code exists
+
+## typescript (new language support in 0.12.0)
+    * [THRIFT-3143] - add typescript directory support
+
+================================================================================
 Thrift 0.11.0
 --------------------------------------------------------------------------------
 ## Sub-task
@@ -179,6 +440,7 @@
     * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures
     * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. 
     * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE
+    * [THRIFT-4375] - TMemory throw bad_alloc due to counter overflow
     * [THRIFT-4376] - Coverity high impact issue resolution
     * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer
     * [THRIFT-4381] - Wrong isset bitfield value after transmission
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0460359..7a1d710 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,6 +6,43 @@
  * [Get involved!](http://www.apache.org/foundation/getinvolved.html)
  * [Legal aspects on Submission of Contributions (Patches)](http://www.apache.org/licenses/LICENSE-2.0.html#contributions)
 
+## GitHub pull requests ##
+
+This is the preferred method of submitting changes.  When you submit a pull request through github,
+it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changesxi
+on a variety of Linux and Windows configurations and run all the test suites.  Follow these requirements 
+for a successful pull request:
+
+ 1. All code changes require an [Apache Jira THRIFT Issue](http://issues.apache.org/jira/browse/THRIFT) ticket.
+
+ 1. All pull requests should contain a single commit per issue, or we will ask you to squash it.
+ 1. The pull request title must begin with the Jira THRIFT ticket identifier, for example:
+
+        THRIFT-9999: an example pull request title
+        
+ 1. Commit messages must follow this pattern for code changes (deviations will not be merged):
+        
+        THRIFT-9999: [summary of fix, one line if possible]
+        Client: [language(s) affected, comma separated, use lib/ directory names please]
+
+Instructions:
+
+ 1. Create a fork in your GitHub account of http://github.com/apache/thrift
+ 1. Clone the fork to your development system.
+ 1. Create a branch for your changes (best practice is issue as branch name, e.g. THRIFT-9999).
+ 1. Modify the source to include the improvement/bugfix, and:
+
+    * Remember to provide *tests* for all submitted changes!
+    * Use test-driven development (TDD): add a test that will isolate the bug *before* applying the change that fixes it.
+    * Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages).
+    * [*optional*] Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs).  You can use this technique to run the Thrift CI jobs in your account to check your changes before they are made public.  Every GitHub pull request into Thrift will run the full CI build and test suite on your changes.
+
+ 1. Squash your changes to a single commit.  This maintains clean change history.
+ 1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. "THRIFT-9999: make it perfect"), with the affected languages on the next line of the description.
+ 1. Use GitHub to create a pull request going from your branch to apache:master.  Ensure that the Jira ticket number is at the beginning of the title of your pull request, same as the commit title.
+ 1. Wait for other contributors or committers to review your new addition, and for a CI build to complete.
+ 1. Wait for a committer to commit your patch.  You can nudge the committers if necessary by sending a message to the [Apache Thrift mailing list](https://thrift.apache.org/mailing).
+
 ## If you want to build the project locally ##
 
 For Windows systems, see our detailed instructions on the [CMake README](/build/cmake/README.md).
@@ -25,26 +62,6 @@
  1. If not, create a ticket describing the change you're proposing in the Jira issue tracker.
  1. Contribute your code changes using the GitHub pull request method:
 
-## Contributing via GitHub pull requests ##
-
-This is the preferred method of submitting changes.  When you submit a pull request through github, it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changes on a variety of Windows and Linux configurations and run all the test suites.
-
- 1. Create a fork in your GitHub account of http://github.com/apache/thrift
- 1. Clone the fork to your development system.
- 1. Create a branch for your changes (best practice is issue as branch name, e.g. THRIFT-9999).
- 1. Modify the source to include the improvement/bugfix, and:
-
-    * Remember to provide *tests* for all submitted changes!
-    * Use test-driven development (TDD): add a test that will isolate the bug *before* applying a  change that fixes it.
-    * Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages).
-    * [*optional*] Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs).  You can use this technique to run the Thrift CI jobs in your account to check your changes before they are made public.  Every GitHub pull request into Thrift will run the full CI build and test suite on your changes.
-
- 1. Squash your changes to a single commit.  This is very important as it makes the process of applying your commit upstream much easier.
- 1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. "THRIFT-9999: make it perfect").
- 1. Use GitHub to create a pull request going from your branch to apache:master.  Ensure that the Jira ticket number is at the beginning of the title of your pull request, same as the commit title.
- 1. Wait for other contributors or committers to review your new addition, and for a CI build to complete.
- 1. Wait for a committer to commit your patch.  You can nudge the committers if necessary by sending a message to the [Apache Thrift mailing list](https://thrift.apache.org/mailing).
-
 ## Contributing via Patch ##
 
 Some changes do not require a build, for example in documentation.  For changes that are not code or build related, you can submit a patch on Jira for review.  To create a patch from changes in your local directory:
diff --git a/LANGUAGES.md b/LANGUAGES.md
index 2f68a4e..24a3cf5 100644
--- a/LANGUAGES.md
+++ b/LANGUAGES.md
@@ -1,20 +1,22 @@
 # Apache Thrift Language Support #
 
-Last Modified: 2017-10-05<br>
-Version: 0.11.0+
+Last Modified: 2018-12-17
+
+Guidance For: 0.12.0 or later
 
 Thrift supports many programming languages and has an impressive test suite that exercises most of the languages, protocols, and transports that represents a matrix of thousands of possible combinations.  Each language typically has a minimum required version as well as support libraries - some mandatory and some optional.  All of this information is provided below to help you assess whether you can use Apache Thrift with your project.  Obviously this is a complex matrix to maintain and may not be correct in all cases - if you spot an error please inform the developers using the mailing list.
 
-Apache Thrift has a choice of two build systems.  The `autoconf` build system is the most complete build and is used to build all supported languages.  The `cmake` build system has been designated by the project to replace `autoconf` however this transition will take quite some time to complete. 
+Apache Thrift has a choice of two build systems.  The `autoconf` build system is the most complete build and is used to build all supported languages.  The `cmake` build system has been designated by the project to replace `autoconf` however this transition will take quite some time to complete.
 
-The Language/Library Levels indicate the minimum and maximum versions that are used in the [continuous integration environments](build/docker/README.md) (Appveyor, Travis) for Apache Thrift.  Note that while a language may contain support for protocols, transports, and servers, the extent to which each is tested as part of the overall build process varies.  The definitive integration test for the project is called the "cross" test which executes a test matrix with clients and servers communicating across languages.
+The Language/Library Levels indicate the minimum and maximum versions that are used in the [continuous integration environments](build/docker/README.md) (Appveyor, Travis) for Apache Thrift.  Other language levels may be supported for each language, however tested less thoroughly; check the README file inside each lib directory for additional details.  Note that while a language may contain support for protocols, transports, and servers, the extent to which each is tested as part of the overall build process varies.  The definitive integration test for the project is called the "cross" test which executes a test matrix with clients and servers communicating across languages.
 
-<table style="font-size: 65%; padding: 1px;">
+<table style="font-size: 60%; padding: 1px;">
 <thead>
 <tr>
 <th rowspan=2>Language</th>
+<th rowspan=2 align=center>Since</th>
 <th colspan=2 align=center>Build Systems</th>
-<th colspan=2 align=center>Lang/Lib Levels</th>
+<th colspan=2 align=center>Lang/Lib Levels (Tested)</th>
 <th colspan=6 align=center>Low-Level Transports</th>
 <th colspan=3 align=center>Transport Wrappers</th>
 <th colspan=4 align=center>Protocols</th>
@@ -33,6 +35,7 @@
 <tbody>
 <tr align=center>
 <td align=left><a href="lib/as3/README.md">ActionScript</a></td>
+<!-- Since -----------------><td>0.3.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td colspan=2>ActionScript 3</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -43,8 +46,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/c_glib/README.md">C (glib)</a></td>
+<!-- Since -----------------><td>0.6.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
-<!-- Language Levels -------><td>2.40.2</td><td>2.54.0</td>
+<!-- Language Levels -------><td>2.48.2</td><td>2.56.0</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -53,8 +57,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/cpp/README.md">C++</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
-<!-- Language Levels -------><td colspan=2>C++98, gcc </td>
+<!-- Language Levels -------><td colspan=2>C++98</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -63,6 +68,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/csharp/README.md">C#</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td>.NET&nbsp;3.5 / mono&nbsp;3.2.8.0</td><td>.NET&nbsp;4.6.1 / mono&nbsp;4.6.2.7</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -73,6 +79,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/cocoa/README.md">Cocoa</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td colspan=2>unknown</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -82,9 +89,21 @@
 <td align=left><a href="https://issues.apache.org/jira/browse/THRIFT/component/12312398">Cocoa</a></td>
 </tr>
 <tr align=center>
-<td align=left><a href="lib/d/README.md">D</a></td>
+<td align=left><a href="lib/cl/README.md">Common Lisp</a></td>
+<!-- Since -----------------><td>0.12.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>2.070.2</td><td>2.076.0</td>
+<!-- Language Levels -------><td>SBCL 1.4.5</td><td>SBCL 1.4.15</td>
+<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
+<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<td align=left><a href="https://issues.apache.org/jira/browse/THRIFT-82">Common Lisp</a></td>
+</tr>
+<tr align=center>
+<td align=left><a href="lib/d/README.md">Dlang</a></td>
+<!-- Since -----------------><td>0.9.0</td>
+<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Language Levels -------><td>2.075.1</td><td>2.083.2</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -93,8 +112,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/dart/README.md">Dart</a></td>
+<!-- Since -----------------><td>0.10.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.20.1</td><td>1.24.2</td>
+<!-- Language Levels -------><td>1.22.1</td><td>1.24.3</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -103,6 +123,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/delphi/README.md">Delphi</a></td>
+<!-- Since -----------------><td>0.8.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td>2010</td><td>unknown</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -113,8 +134,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/netcore/README.md">.NET Core</a></td>
-<!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>2.0.0</td><td>2.0.3</td>
+<!-- Since -----------------><td>0.11.0</td>
+<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Language Levels -------><td>2.1.4</td><td>2.2.101</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -123,8 +145,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/erl/README.md">Erlang</a></td>
+<!-- Since -----------------><td>0.3.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>R16B03</td><td>20.0.4</td>
+<!-- Language Levels -------><td>18.3</td><td>20.0.4</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -133,8 +156,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/go/README.md">Go</a></td>
+<!-- Since -----------------><td>0.7.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.2.1</td><td>1.8.3</td>
+<!-- Language Levels -------><td>1.7.6</td><td>1.11.4</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -143,8 +167,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/hs/README.md">Haskell</a></td>
+<!-- Since -----------------><td>0.5.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
-<!-- Language Levels -------><td>7.6.3</td><td>8.0.2</td>
+<!-- Language Levels -------><td>7.10.3</td><td>8.0.2</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -153,8 +178,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/haxe/README.md">Haxe</a></td>
+<!-- Since -----------------><td>0.9.3</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td colspan=2>3.2.1</td>
+<!-- Language Levels -------><td>3.2.1</td><td>3.4.4</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -163,8 +189,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/java/README.md">Java (SE)</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
-<!-- Language Levels -------><td>1.7.0_151</td><td>1.8.0_144</td>
+<!-- Language Levels -------><td>1.8.0_151</td><td>1.8.0_191</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -173,6 +200,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/javame/README.md">Java (ME)</a></td>
+<!-- Since -----------------><td>0.5.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td colspan=2>unknown</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -183,6 +211,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/js/README.md">Javascript</a></td>
+<!-- Since -----------------><td>0.3.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td colspan=2>unknown</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -193,6 +222,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/lua/README.md">Lua</a></td>
+<!-- Since -----------------><td>0.9.2</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td>5.1.5</td><td>5.2.4</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -203,18 +233,31 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/nodejs/README.md">node.js</a></td>
+<!-- Since -----------------><td>0.6.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>4.2.6</td><td>8.9.1</td>
-<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
+<!-- Language Levels -------><td>6.x</td><td>8.x</td>
+<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <td align=left><a href="https://issues.apache.org/jira/browse/THRIFT/component/12314320">node.js</a></td>
 </tr>
 <tr align=center>
+<td align=left><a href="lib/nodets/README.md">node.ts</a></td>
+<!-- Since -----------------><td>0.12.0</td>
+<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Language Levels -------><td>3.1.6</td><td></td>
+<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
+<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
+<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20resolution%20%3D%20Unresolved%20and%20Component%20in%20(%22TypeScript%20-%20Library%22)%20ORDER%20BY%20priority%20DESC%2C%20updated%20DESC">node.ts</a></td>
+</tr>
+<tr align=center>
 <td align=left><a href="lib/ocaml/README.md">OCaml</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>4.02.3</td><td>4.04.0</td>
+<!-- Language Levels -------><td colspan=2>4.04.0</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -223,8 +266,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/perl/README.md">Perl</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>5.18.2</td><td>5.26.0</td>
+<!-- Language Levels -------><td>5.22.1</td><td>5.26.1</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -233,8 +277,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/php/README.md">PHP</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>5.5.9</td><td>7.1.8</td>
+<!-- Language Levels -------><td>7.0.22</td><td>7.2.10</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -243,8 +288,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/py/README.md">Python</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
-<!-- Language Levels -------><td>2.7.6, 3.4.3</td><td>2.7.14, 3.6.3</td>
+<!-- Language Levels -------><td>2.7.12, 3.5.2</td><td>2.7.15rc1, 3.6.7</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -253,8 +299,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/rb/README.md">Ruby</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.9.3p484</td><td>2.3.3p222</td>
+<!-- Language Levels -------><td>2.3.1p112</td><td>2.5.1p57</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -263,8 +310,9 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/rs/README.md">Rust</a></td>
+<!-- Since -----------------><td>0.11.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.15.1</td><td>1.18.0</td>
+<!-- Language Levels -------><td>1.17.0</td><td>1.30.0</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
@@ -273,6 +321,7 @@
 </tr>
 <tr align=center>
 <td align=left><a href="lib/st/README.md">Smalltalk</a></td>
+<!-- Since -----------------><td>0.2.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Language Levels -------><td colspan=2>unknown</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
@@ -285,6 +334,7 @@
 <tfoot>
 <tr>
 <th rowspan=2>Language</th>
+<th rowspan=2 align=center>Since</th>
 <!-- Build Systems ---------><th>autoconf</th><th>cmake</th>
 <!-- Lang/Lib Levels -------><th>Min</th><th>Max</th>
 <!-- Low-Level Transports --><th><a href="https://en.wikipedia.org/wiki/Unix_domain_socket">Domain</a></th></th><th>&nbsp;File&nbsp;</th><th>Memory</th><th>&nbsp;Pipe&nbsp;</th><th>Socket</th><th>&nbsp;TLS&nbsp;</th>
@@ -295,7 +345,7 @@
 </tr>
 <tr>
 <th colspan=2 align=center>Build Systems</th>
-<th colspan=2 align=center>Lang/Lib Levels</th>
+<th colspan=2 align=center>Lang/Lib Levels (Tested)</th>
 <th colspan=6 align=center>Low-Level Transports</th>
 <th colspan=3 align=center>Transport Wrappers</th>
 <th colspan=4 align=center>Protocols</th>
diff --git a/Makefile.am b/Makefile.am
index 3d71fd4..511452d 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,7 @@
 space := $(empty) $(empty)
 comma := ,
 
-CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@
+CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@ @MAYBE_NODETS@
 CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS))
 
 if WITH_PY3
@@ -65,14 +65,14 @@
 
 if WITH_PYTHON
 crossfeature: precross
-	$(CROSS_PY) test/test.py --retry-count 3 --features .* --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED)
+	$(CROSS_PY) test/test.py --retry-count 5 --features .* --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED)
 else
 # feature test needs python build
 crossfeature:
 endif
 
 cross-%: precross crossfeature
-	$(CROSS_PY) test/test.py --retry-count 3 --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) --client $(CROSS_LANGS_COMMA_SEPARATED) --regex "$*"
+	$(CROSS_PY) test/test.py --retry-count 5 --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) --client $(CROSS_LANGS_COMMA_SEPARATED) --regex "$*"
 
 cross: cross-.*
 
diff --git a/README.md b/README.md
index 5435041..d09e6e1 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,43 @@
 Apache Thrift
 =============
 
-Last Modified: 2017-11-10
+Introduction
+============
+
+Thrift is a lightweight, language-independent software stack with an
+associated code generation mechanism for point-to-point RPC. Thrift provides 
+clean abstractions for data transport, data serialization, and application
+level processing. The code generation system takes a simple definition
+language as input and generates code across programming languages that
+uses the abstracted stack to build interoperable RPC clients and servers.
+
+![Apache Thrift Layered Architecture](doc/images/thrift-layers.png)
+
+Thrift makes it easy for programs written in different programming
+languages to share data and call remote procedures.  With support 
+for [25 programming languages](LANGUAGES.md), chances are Thrift 
+supports the languages that you currently use.
+
+Thrift is specifically designed to support non-atomic version changes
+across client and server code.
+
+For more details on Thrift's design and implementation, see the Thrift
+whitepaper included in this distribution, or at the README.md file
+in your particular subdirectory of interest.
+
+Status
+======
+
+| Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website |
+| :----- | :----- | :------- | :------------ | :--------- | :------ |
+| [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) |
+
+Releases
+========
+
+Thrift does not maintain a specific release calendar at this time.  
+
+We strive to release twice yearly.  Download the [current release](http://thrift.apache.org/download).
 
 License
 =======
@@ -23,30 +59,6 @@
 specific language governing permissions and limitations
 under the License.
 
-Introduction
-============
-
-Thrift is a lightweight, language-independent software stack with an
-associated code generation mechanism for RPC. Thrift provides clean
-abstractions for data transport, data serialization, and application
-level processing. The code generation system takes a simple definition
-language as its input and generates code across programming languages that
-uses the abstracted stack to build interoperable RPC clients and servers.
-
-![Apache Thrift Layered Architecture](doc/images/thrift-layers.png)
-
-Thrift makes it easy for programs written in different programming
-languages to share data and call remote procedures.  With support 
-for [over 20 programming languages](LANGUAGES.md), chances are Thrift 
-supports the ones that you currently use.
-
-Thrift is specifically designed to support non-atomic version changes
-across client and server code.
-
-For more details on Thrift's design and implementation, take a gander at
-the Thrift whitepaper included in this distribution or at the README.md file
-in your particular subdirectory of interest.
-
 Project Hierarchy
 =================
 
@@ -79,10 +91,16 @@
     Contains a basic tutorial that will teach you how to develop software
     using Thrift.
 
+Development
+===========
+
+To build the same way Travis CI builds the project you should use docker.
+We have [comprehensive building instructions for docker](build/docker/README.md).
+
 Requirements
 ============
 
-See http://thrift.apache.org/docs/install for an up-to-date list of build requirements.
+See http://thrift.apache.org/docs/install for a list of build requirements (may be stale).  Alternatively see the docker build environments for a list of prerequisites.
 
 Resources
 =========
@@ -171,8 +189,4 @@
 This will run a set of tests that use different language clients and
 servers.
 
-Development
-===========
 
-To build the same way Travis CI builds the project you should use docker.
-We have [comprehensive building instructions for docker](build/docker/README.md).
diff --git a/Thrift-swift3.podspec b/Thrift-swift3.podspec
new file mode 100644
index 0000000..126c00b
--- /dev/null
+++ b/Thrift-swift3.podspec
@@ -0,0 +1,16 @@
+Pod::Spec.new do |s|
+  s.name          = "Thrift-swift3"
+  s.version       = "1.0.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 scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages.
+                    DESC
+  s.homepage      = "http://thrift.apache.org"
+  s.license       = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' }
+  s.author        = { "Apache Thrift Developers" => "dev@thrift.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 => "v1.0.0" }
+  s.source_files  = "lib/swift/Sources/*.swift"
+end
diff --git a/Thrift.podspec b/Thrift.podspec
index 6f8ebb7..a406eec 100644
--- a/Thrift.podspec
+++ b/Thrift.podspec
@@ -1,18 +1,18 @@
 Pod::Spec.new do |s|
   s.name          = "Thrift"
-  s.version       = "0.11.0"
+  s.version       = "1.0.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.
+The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming 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.license       = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' }
+  s.author        = { "Apache Thrift Developers" => "dev@thrift.apache.org" }
   s.requires_arc  = true
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.8'
   s.ios.framework = 'CFNetwork'
   s.osx.framework = 'CoreServices'
-  s.source        = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-0.11.0" }
+  s.source        = { :git => "https://github.com/apache/thrift.git", :tag => "v1.0.0" }
   s.source_files  = 'lib/cocoa/src/**/*.{h,m,swift}'
-end
\ No newline at end of file
+end
diff --git a/aclocal/ax_boost_base.m4 b/aclocal/ax_boost_base.m4
index 19c71b6..d540395 100644
--- a/aclocal/ax_boost_base.m4
+++ b/aclocal/ax_boost_base.m4
@@ -33,7 +33,7 @@
 #   and this notice are preserved. This file is offered as-is, without any
 #   warranty.
 
-#serial 42
+#serial 45
 
 # example boost program (need to pass version)
 m4_define([_AX_BOOST_BASE_PROGRAM],
@@ -113,8 +113,8 @@
     dnl are found, e.g. when only header-only libraries are installed!
     AS_CASE([${host_cpu}],
       [x86_64],[libsubdirs="lib64 libx32 lib lib64"],
-      [ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
-      [libsubdirs="lib"],
+      [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"],
+      [libsubdirs="lib"]
     )
 
     dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
diff --git a/aclocal/ax_cxx_compile_stdcxx.m4 b/aclocal/ax_cxx_compile_stdcxx.m4
index 5032bba..9e9eaed 100644
--- a/aclocal/ax_cxx_compile_stdcxx.m4
+++ b/aclocal/ax_cxx_compile_stdcxx.m4
@@ -33,19 +33,18 @@
 #   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
 #   Copyright (c) 2015 Paul Norman <penorman@mac.com>
 #   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
-#   Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
+#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
 #
 #   Copying and distribution of this file, with or without modification, are
 #   permitted in any medium without royalty provided the copyright notice
 #   and this notice are preserved.  This file is offered as-is, without any
 #   warranty.
 
-#serial 7
+#serial 10
 
 dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
 dnl  (serial version number 13).
 
-AX_REQUIRE_DEFINED([AC_MSG_WARN])
 AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
   m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
         [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
@@ -61,14 +60,6 @@
         [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
   AC_LANG_PUSH([C++])dnl
   ac_success=no
-  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
-  ax_cv_cxx_compile_cxx$1,
-  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
-    [ax_cv_cxx_compile_cxx$1=yes],
-    [ax_cv_cxx_compile_cxx$1=no])])
-  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
-    ac_success=yes
-  fi
 
   m4_if([$2], [noext], [], [dnl
   if test x$ac_success = xno; then
@@ -139,7 +130,6 @@
               [define if the compiler supports basic C++$1 syntax])
   fi
   AC_SUBST(HAVE_CXX$1)
-  m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
 ])
 
 
@@ -587,20 +577,12 @@
 
 #error "This is not a C++ compiler"
 
-#elif __cplusplus <= 201402L
+#elif __cplusplus < 201703L
 
 #error "This is not a C++17 compiler"
 
 #else
 
-#if defined(__clang__)
-  #define REALLY_CLANG
-#else
-  #if defined(__GNUC__)
-    #define REALLY_GCC
-  #endif
-#endif
-
 #include <initializer_list>
 #include <utility>
 #include <type_traits>
@@ -608,16 +590,12 @@
 namespace cxx17
 {
 
-#if !defined(REALLY_CLANG)
   namespace test_constexpr_lambdas
   {
 
-    // TODO: test it with clang++ from git
-
     constexpr int foo = [](){return 42;}();
 
   }
-#endif // !defined(REALLY_CLANG)
 
   namespace test::nested_namespace::definitions
   {
@@ -852,12 +830,9 @@
 
   }
 
-#if !defined(REALLY_CLANG)
   namespace test_template_argument_deduction_for_class_templates
   {
 
-    // TODO: test it with clang++ from git
-
     template <typename T1, typename T2>
     struct pair
     {
@@ -876,7 +851,6 @@
     }
 
   }
-#endif // !defined(REALLY_CLANG)
 
   namespace test_non_type_auto_template_parameters
   {
@@ -890,12 +864,9 @@
 
   }
 
-#if !defined(REALLY_CLANG)
   namespace test_structured_bindings
   {
 
-    // TODO: test it with clang++ from git
-
     int arr[2] = { 1, 2 };
     std::pair<int, int> pr = { 1, 2 };
 
@@ -927,14 +898,10 @@
     const auto [ x3, y3 ] = f3();
 
   }
-#endif // !defined(REALLY_CLANG)
 
-#if !defined(REALLY_CLANG)
   namespace test_exception_spec_type_system
   {
 
-    // TODO: test it with clang++ from git
-
     struct Good {};
     struct Bad {};
 
@@ -952,7 +919,6 @@
     static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
 
   }
-#endif // !defined(REALLY_CLANG)
 
   namespace test_inline_variables
   {
@@ -977,6 +943,6 @@
 
 }  // namespace cxx17
 
-#endif  // __cplusplus <= 201402L
+#endif  // __cplusplus < 201703L
 
 ]])
diff --git a/appveyor.yml b/appveyor.yml
index 073ffd4..e021479 100755
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -19,45 +19,55 @@
 
 # build Apache Thrift on AppVeyor - https://ci.appveyor.com
 
-version: '0.11.0.{build}'
+version: '1.0.0.{build}'
 
 shallow_clone: true
 
 os:
-  - Visual Studio 2015
+  - Visual Studio 2017
 
-cache:
-  - C:\projects\thrift\buildcache -> build\appveyor\MSVC-appveyor-install.bat
-  - C:\ProgramData\chocolatey\lib -> build\appveyor\MSVC-appveyor-install.bat
-  - C:\msys64\var\cache\pacman    -> build\appveyor\MSYS-appveyor-install.bat
+matrix:
+  allow_failures:
+      - PROFILE: CYGWIN
+  fast_finish: true
 
 environment:
   matrix:
-   - PROFILE: MSVC2010
-     PLATFORM: x86
-     CONFIGURATION: Debug
-     BOOST_VERSION: 1.54.0
-     LIBEVENT_VERSION: 2.0.22
-     QT_VERSION: 5.6
-     ZLIB_VERSION: 1.2.8
-     DISABLED_TESTS: StressTestNonBlocking
-
-   - PROFILE: MSVC2015
+   - PROFILE: MSVC2017
      PLATFORM: x64
      CONFIGURATION: Release
-     BOOST_VERSION: 1.64.0
-     LIBEVENT_VERSION: 2.0.22
+     BOOST_VERSION: 1.65.1
+     LIBEVENT_VERSION: 2.1.8
      PYTHON_VERSION: 3.6
-     QT_VERSION: 5.8
+     QT_VERSION: 5.10
      ZLIB_VERSION: 1.2.11
      DISABLED_TESTS: StressTestNonBlocking
 
+   - PROFILE: MSVC2013
+     PLATFORM: x86
+     CONFIGURATION: Release
+     BOOST_VERSION: 1.58.0
+     LIBEVENT_VERSION: 2.0.22
+     PYTHON_VERSION: 3.5
+     QT_VERSION: 5.8
+     ZLIB_VERSION: 1.2.8
+     DISABLED_TESTS: StressTestNonBlocking
+     APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+
    - PROFILE: MINGW
      PLATFORM: x64
-     CONFIGURATION: Release
+     CONFIGURATION: RelWithDebInfo
+     DISABLED_TESTS: StressTestNonBlocking
 
-matrix:
-  fast_finish: true
+   - PROFILE: CYGWIN
+     PLATFORM: x86
+     CONFIGURATION: RelWithDebInfo
+     DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking)
+
+#  - PROFILE: CYGWIN
+#    PLATFORM: x64
+#    CONFIGURATION: RelWithDebInfo
+#    DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking)
 
 install:
   - cd %APPVEYOR_BUILD_FOLDER%
@@ -98,4 +108,3 @@
 # also need:
 # environment:
 #   APPVEYOR_RDP_PASSWORD: thr1FT2345$xyzZ
-
diff --git a/bootstrap.sh b/bootstrap.sh
index c7e000c..2452eea 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -38,10 +38,14 @@
   exit 1
 fi
 
+format_version () {
+    printf "%03d%03d%03d%03d" $(echo $1 | tr '.' ' ');
+}
+
 # we require automake 1.13 or later
 # check must happen externally due to use of newer macro
 AUTOMAKE_VERSION=`automake --version | grep automake | egrep -o '([0-9]{1,}\.)+[0-9]{1,}'`
-if [ "$AUTOMAKE_VERSION" \< "1.13" ]; then
+if  [ $(format_version $AUTOMAKE_VERSION) -lt $(format_version 1.13) ]; then
   echo >&2 "automake version $AUTOMAKE_VERSION is too old (need 1.13 or later)"
   exit 1
 fi
diff --git a/bower.json b/bower.json
index 1092c65..853b8cb 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,7 @@
 {
   "name": "thrift",
-  "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git",
+  "version": "1.0.0",
+  "homepage": "https://github.com/apache/thrift.git",
   "authors": [
     "Apache Thrift <dev@thrift.apache.org>"
   ],
@@ -10,6 +11,5 @@
     "thrift"
   ],
   "license": "Apache v2",
-  "ignore": [
-  ]
+  "ignore": []
 }
diff --git a/build/appveyor/CYGW-appveyor-build.bat b/build/appveyor/CYGW-appveyor-build.bat
new file mode 100644
index 0000000..c226222
--- /dev/null
+++ b/build/appveyor/CYGW-appveyor-build.bat
@@ -0,0 +1,36 @@
+::
+:: Licensed 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.
+::
+
+@ECHO OFF
+SETLOCAL EnableDelayedExpansion
+
+CD build\appveyor                           || EXIT /B
+CALL cl_banner_build.bat                    || EXIT /B
+CALL cl_setenv.bat                          || EXIT /B
+
+SET CMAKEARGS=^
+  -G'%GENERATOR%' ^
+  -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
+  -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^
+  -DCMAKE_CXX_EXTENSIONS=ON ^
+  -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE" ^
+  -DCMAKE_CXX_STANDARD=11 ^
+  -DWITH_PYTHON=OFF ^
+  -DWITH_SHARED_LIB=OFF ^
+  -DWITH_STATIC_LIB=ON ^
+  -DWITH_STDTHREADS=ON
+
+@ECHO ON
+%BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B
+@ECHO OFF
diff --git a/build/appveyor/CYGW-appveyor-install.bat b/build/appveyor/CYGW-appveyor-install.bat
new file mode 100644
index 0000000..77db7d4
--- /dev/null
+++ b/build/appveyor/CYGW-appveyor-install.bat
@@ -0,0 +1,34 @@
+::
+:: Licensed 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.
+::
+
+::
+:: Appveyor install script for CYGWIN
+:: Installs third party packages we need for a cmake build
+::
+
+@ECHO OFF
+SETLOCAL EnableDelayedExpansion
+
+CD build\appveyor                          || EXIT /B
+CALL cl_banner_install.bat                 || EXIT /B
+CALL cl_setenv.bat                         || EXIT /B
+CALL cl_showenv.bat                        || EXIT /B
+
+::
+:: Install apt-cyg for package management
+::
+
+%BASH% -lc "wget rawgit.com/transcode-open/apt-cyg/master/apt-cyg && install apt-cyg /bin && rm -f apt-cyg" || EXIT /B
+%BASH% -lc "apt-cyg update" || EXIT /B
+%BASH% -lc "apt-cyg install bison cmake flex gcc-g++ libboost-devel libevent-devel make openssl-devel zlib-devel"
diff --git a/build/appveyor/CYGW-appveyor-test.bat b/build/appveyor/CYGW-appveyor-test.bat
new file mode 100644
index 0000000..b667f9b
--- /dev/null
+++ b/build/appveyor/CYGW-appveyor-test.bat
@@ -0,0 +1,21 @@
+::
+:: Licensed 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.
+::
+
+@ECHO OFF
+SETLOCAL EnableDelayedExpansion
+CD build\appveyor              || EXIT /B
+CALL cl_banner_test.bat        || EXIT /B
+CALL cl_setenv.bat             || EXIT /B
+
+%BASH% -lc "cd %BUILDDIR% && ctest.exe -C %CONFIGURATION% --timeout 300 -VV -E '%DISABLED_TESTS%'" || EXIT /B
diff --git a/build/appveyor/MING-appveyor-build.bat b/build/appveyor/MING-appveyor-build.bat
index 838e428..b37a95a 100644
--- a/build/appveyor/MING-appveyor-build.bat
+++ b/build/appveyor/MING-appveyor-build.bat
@@ -22,15 +22,15 @@
 SET CMAKEARGS=^
   -G'%GENERATOR%' ^
   -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
-  -DCMAKE_INSTALL_PREFIX=%INSTDIR_MSYS% ^
-  -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make ^
-  -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc.exe ^
-  -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe ^
-  -DWITH_LIBEVENT=OFF ^
+  -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^
+  -DCMAKE_MAKE_PROGRAM=/mingw%NORM_PLATFORM%/bin/mingw32-make ^
+  -DCMAKE_C_COMPILER=/mingw%NORM_PLATFORM%/bin/gcc.exe ^
+  -DCMAKE_CXX_COMPILER=/mingw%NORM_PLATFORM%/bin/g++.exe ^
+  -DOPENSSL_ROOT_DIR=/mingw%NORM_PLATFORM% ^
   -DWITH_PYTHON=OFF ^
   -DWITH_SHARED_LIB=OFF ^
   -DWITH_STATIC_LIB=ON
 
 @ECHO ON
-%BASH% -lc "mkdir -p %BUILDDIR_MSYS% && cd %BUILDDIR_MSYS% && cmake.exe %SRCDIR_MSYS% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B
+%BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B
 @ECHO OFF
diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat
index 0d5f99e..1069b05 100644
--- a/build/appveyor/MING-appveyor-install.bat
+++ b/build/appveyor/MING-appveyor-install.bat
@@ -13,9 +13,33 @@
 ::
 
 ::
-:: Appveyor install script for MinGW
-:: Installs (or builds) third party packages we need
+:: Appveyor install script for MINGW on MSYS2
+:: Installs third party packages we need for a cmake build
 ::
 
-:: Same as the MSYS installation requirements
-CALL build\appveyor\MSYS-appveyor-install.bat
+@ECHO OFF
+SETLOCAL EnableDelayedExpansion
+
+CD build\appveyor                          || EXIT /B
+CALL cl_banner_install.bat                 || EXIT /B
+CALL cl_setenv.bat                         || EXIT /B
+CALL cl_showenv.bat                        || EXIT /B
+
+SET PACKAGES=^
+  --needed -S bison flex make ^
+  mingw-w64-%MINGWPLAT%-boost ^
+  mingw-w64-%MINGWPLAT%-cmake ^
+  mingw-w64-%MINGWPLAT%-libevent ^
+  mingw-w64-%MINGWPLAT%-openssl ^
+  mingw-w64-%MINGWPLAT%-toolchain ^
+  mingw-w64-%MINGWPLAT%-zlib
+
+::mingw-w64-%MINGWPLAT%-qt5 : WAY too large (1GB download!) - tested in cygwin builds anyway
+
+:: Remove old packages that no longer exist to avoid an error
+%BASH% -lc "pacman --noconfirm --remove libcatgets catgets || true" || EXIT /B
+
+:: Upgrade things
+%BASH% -lc "pacman --noconfirm -Syu %IGNORE%"                       || EXIT /B
+%BASH% -lc "pacman --noconfirm -Su %IGNORE%"                        || EXIT /B
+%BASH% -lc "pacman --noconfirm %PACKAGES%"                          || EXIT /B
\ No newline at end of file
diff --git a/build/appveyor/MING-appveyor-test.bat b/build/appveyor/MING-appveyor-test.bat
index c37c72a..499c1ff 100644
--- a/build/appveyor/MING-appveyor-test.bat
+++ b/build/appveyor/MING-appveyor-test.bat
@@ -12,5 +12,11 @@
 :: limitations under the License.
 ::
 
-:: Same as MSYS2
-CALL build\appveyor\MSYS-appveyor-test.bat
+@ECHO OFF
+SETLOCAL EnableDelayedExpansion
+
+CD build\appveyor              || EXIT /B
+CALL cl_banner_test.bat        || EXIT /B
+CALL cl_setenv.bat             || EXIT /B
+
+%BASH% -lc "cd %BUILDDIR% && ctest.exe -C %CONFIGURATION% --timeout 300 -VV -E '%DISABLED_TESTS%'" || EXIT /B
diff --git a/build/appveyor/MSVC-appveyor-install.bat b/build/appveyor/MSVC-appveyor-install.bat
index 573700e..f973d29 100644
--- a/build/appveyor/MSVC-appveyor-install.bat
+++ b/build/appveyor/MSVC-appveyor-install.bat
@@ -26,47 +26,34 @@
 CALL cl_showenv.bat                       || EXIT /B
 MKDIR "%WIN3P%"                           || EXIT /B
 
-:: Install ant - this also installs the latest JDK as a dependency
-:: The installation of JDK requires us to pick up PATH and JAVE_HOME from the registry
-cinst -c "%BUILDCACHE%" -y ant            || EXIT /B
+choco feature enable -n allowGlobalConfirmation || EXIT /B
 
-:: Install bison and flex
-cinst -c "%BUILDCACHE%" -y winflexbison3  || EXIT /B
+:: Things to install when NOT running in appveyor:
+IF "%APPVEYOR_BUILD_ID%" == "" (
+    cup -y chocolatey                     || EXIT /B
+    cinst -y curl                         || EXIT /B
+    cinst -y 7zip                         || EXIT /B
+    cinst -y python3                      || EXIT /B
+    cinst -y openssl.light                || EXIT /B
+)
 
-:: zlib
+cinst -y jdk8                             || EXIT /B
+cinst -y winflexbison3                    || EXIT /B
+
+:: zlib - not available through chocolatey
 CD "%APPVEYOR_SCRIPTS%"                   || EXIT /B
 call build-zlib.bat                       || EXIT /B
 
-:: libevent
+:: libevent - not available through chocolatey
 CD "%APPVEYOR_SCRIPTS%"                   || EXIT /B
 call build-libevent.bat                   || EXIT /B
 
-:: python packages
-pip install backports.ssl_match_hostname ^
+:: python packages (correct path to pip set in cl_setenv.bat)
+pip.exe ^
+    install backports.ssl_match_hostname ^
             ipaddress ^
+            six ^
             tornado ^
             twisted                       || EXIT /B
 
-:: msinttypes - for MSVC2010 only
-SET MSINTTYPESURL=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/msinttypes/msinttypes-r26.zip
-IF "%COMPILER%" == "vc100" (
-  MKDIR "%WIN3P%\msinttypes"              || EXIT /B
-  CD "%WIN3P%\msinttypes"                 || EXIT /B
-  appveyor DownloadFile "%MSINTTYPESURL%" || EXIT /B
-  7z x "msinttypes-r26.zip"               || EXIT /B
-)
-
-:: appveyor build slaves do not have MSVC2010 Boost installed
-IF "%COMPILER%" == "vc100" (
-  SET BITS=64
-  IF "%PLATFORM%" == "x86" (
-    SET BITS=32
-  )
-  SET BOOSTEXEURL=https://downloads.sourceforge.net/project/boost/boost-binaries/%BOOST_VERSION%/boost_%BOOST_VERSION:.=_%-msvc-10.0-!BITS!.exe
-  SET BOOSTEXE=C:\projects\thrift\buildcache\boost_%BOOST_VERSION:.=_%-msvc-10.0-!BITS!.exe
-  appveyor DownloadFile "!BOOSTEXEURL!" -FileName "!BOOSTEXE!" || EXIT /B
-  "!BOOSTEXE!" /dir=C:\Libraries\boost_%BOOST_VERSION:.=_% /silent || EXIT /B
-)
-
-:: Haskell (GHC) and cabal
-cinst -c "%BUILDCACHE%" -y ghc            || EXIT /B
+cinst -y ghc                              || EXIT /B
diff --git a/build/appveyor/MSVC-appveyor-test.bat b/build/appveyor/MSVC-appveyor-test.bat
index 16ee207..3594579 100644
--- a/build/appveyor/MSVC-appveyor-test.bat
+++ b/build/appveyor/MSVC-appveyor-test.bat
@@ -12,14 +12,21 @@
 :: limitations under the License.
 ::
 
-@ECHO OFF
+@ECHO ON
 SETLOCAL EnableDelayedExpansion
 CD build\appveyor              || EXIT /B
 CALL cl_banner_test.bat        || EXIT /B
 CALL cl_setenv.bat             || EXIT /B
 CD "%BUILDDIR%"                || EXIT /B
 
-:: Add directories to the path to find DLLs of third party libraries so tests run
-SET PATH=%BOOST_LIBRARYDIR%;%OPENSSL_ROOT%\bin;%WIN3P%\zlib-inst\bin;%PATH%
+DIR C:\libraries
+DIR C:\libraries\boost_1_59_0
+DIR C:\libraries\boost_1_60_0
+DIR C:\libraries\boost_1_62_0
+DIR C:\libraries\boost_1_63_0
+DIR C:\libraries\boost_1_64_0
+
+:: Add directories to the path to find DLLs of third party libraries so tests run properly!
+SET PATH=%BOOST_LIBRARYDIR:/=\%;%OPENSSL_ROOT%\bin;%WIN3P%\zlib-inst\bin;%PATH%
 
 ctest -C %CONFIGURATION% --timeout 300 -VV -E "(%DISABLED_TESTS%)" || EXIT /B
diff --git a/build/appveyor/MSYS-appveyor-build.bat b/build/appveyor/MSYS-appveyor-build.bat
index b9d8955..4401729 100644
--- a/build/appveyor/MSYS-appveyor-build.bat
+++ b/build/appveyor/MSYS-appveyor-build.bat
@@ -33,12 +33,13 @@
   -DCMAKE_CXX_COMPILER=g++.exe ^
   -DCMAKE_MAKE_PROGRAM=make.exe ^
   -DCMAKE_INSTALL_PREFIX=%INSTDIR_MSYS% ^
+  -DLIBEVENT_ROOT=%LIBEVENT_ROOT% ^
   -DOPENSSL_LIBRARIES=%OPENSSL_LIBRARIES% ^
   -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT% ^
   -DOPENSSL_USE_STATIC_LIBS=ON ^
   -DWITH_BOOST_STATIC=ON ^
   -DWITH_JAVA=OFF ^
-  -DWITH_LIBEVENT=OFF ^
+  -DWITH_LIBEVENT=ON ^
   -DWITH_PYTHON=%WITH_PYTHON% ^
   -DWITH_SHARED_LIB=OFF ^
   -DWITH_STATIC_LIB=ON
diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat
index ff43cd3..a818df3 100644
--- a/build/appveyor/MSYS-appveyor-install.bat
+++ b/build/appveyor/MSYS-appveyor-install.bat
@@ -25,17 +25,24 @@
 CALL cl_setenv.bat                         || EXIT /B
 CALL cl_showenv.bat                        || EXIT /B
 
+:: We're going to keep boost at a version cmake understands
+SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz
+SET IGNORE=--ignore mingw-w64-x86_64-boost
+
 SET PACKAGES=^
-  --needed -S bison flex ^
-  make ^
-  mingw-w64-x86_64-boost ^
+  --needed -S bison flex make ^
   mingw-w64-x86_64-cmake ^
+  mingw-w64-x86_64-libevent ^
   mingw-w64-x86_64-openssl ^
   mingw-w64-x86_64-toolchain ^
   mingw-w64-x86_64-zlib
 
-:: omitting libevent-devel for now it is version 2.1.4 and doesn't play nice with MinGW
+%BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B
+%BASH% -lc "pacman --noconfirm -Su %IGNORE%"  || EXIT /B
+%BASH% -lc "pacman --noconfirm %PACKAGES%"    || EXIT /B
 
-%BASH% -lc "pacman --noconfirm -Syu"       || EXIT /B
-%BASH% -lc "pacman --noconfirm -Su"        || EXIT /B
-%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B
+:: Install a slightly older boost (1.64.0) as cmake 3.10
+:: does not have built-in dependencies for boost 1.66.0 yet
+:: -- this cuts down on build warning output --
+%BASH% -lc "wget http://repo.msys2.org/mingw/x86_64/%BOOSTPKG% && pacman --noconfirm --needed -U %BOOSTPKG% && rm %BOOSTPKG%" || EXIT /B
+
diff --git a/build/appveyor/build-libevent.bat b/build/appveyor/build-libevent.bat
index 13c74ee..64b635b 100644
--- a/build/appveyor/build-libevent.bat
+++ b/build/appveyor/build-libevent.bat
@@ -17,14 +17,21 @@
 SET URLFILE=libevent-%LIBEVENT_VERSION%-stable.tar.gz
 SET URL=https://github.com/libevent/libevent/releases/download/release-%LIBEVENT_VERSION%-stable/%URLFILE%
 
-CD %WIN3P%                                       || EXIT /B
-appveyor DownloadFile %URL%                      || EXIT /B
-7z x %URLFILE% -so | 7z x -si -ttar > nul        || EXIT /B
+:: Download - support running a local build or a build in appveyor
+CD "%WIN3P%"                                     || EXIT /B
+IF "%APPVEYOR_BUILD_ID%" == "" (
+    curl -L -f -o "%URLFILE%" "%URL%"
+) ELSE (
+    appveyor DownloadFile "%URL%"
+)
+7z x "%URLFILE%" -so | 7z x -si -ttar > nul      || EXIT /B
 CD "libevent-%LIBEVENT_VERSION%-stable"          || EXIT /B
-nmake -f Makefile.nmake                          || EXIT /B
+nmake -f Makefile.nmake static_libs              || EXIT /B
+
+:: in libevent 2.0 there is no nmake subdirectory in WIN32-Code, but in 2.1 there is
 mkdir lib                                        || EXIT /B
 move *.lib lib\                                  || EXIT /B
-move WIN32-Code\event2\* include\event2\         || EXIT /B
+move WIN32-Code\event2\* include\event2\         || move WIN32-Code\nmake\event2\* include\event2\ || EXIT /B
 move *.h include\                                || EXIT /B
 
 ENDLOCAL
diff --git a/build/appveyor/build-zlib.bat b/build/appveyor/build-zlib.bat
index d8811a1..9195726 100644
--- a/build/appveyor/build-zlib.bat
+++ b/build/appveyor/build-zlib.bat
@@ -24,11 +24,18 @@
 SET URL=http://zlib.net/%URLFILE%
 SET FURL=http://zlib.net/fossils/%URLFILE%
 
-:: Download
+:: Download - support running a local build or a build in appveyor
 CD "%WIN3P%"                                                     || EXIT /B
-appveyor DownloadFile "%URL%"
-IF ERRORLEVEL 1 (
-    appveyor DownloadFile "%FURL%"                               || EXIT /B
+IF "%APPVEYOR_BUILD_ID%" == "" (
+    curl -L -f -o "%URLFILE%" "%URL%"
+    IF ERRORLEVEL 1 (
+        curl -L -f -o "%URLFILE%" "%FURL%"
+    )
+) ELSE (
+    appveyor DownloadFile "%URL%"
+    IF ERRORLEVEL 1 (
+        appveyor DownloadFile "%FURL%"                           || EXIT /B
+    )
 )
 7z x "%URLFILE%" -so | 7z x -si -ttar > nul                      || EXIT /B
 
diff --git a/build/appveyor/cl_setcompiler.bat b/build/appveyor/cl_setcompiler.bat
index b97da73..733ffc5 100644
--- a/build/appveyor/cl_setcompiler.bat
+++ b/build/appveyor/cl_setcompiler.bat
@@ -20,7 +20,7 @@
 ::   vc110 = Visual Studio 2012
 ::   vc120 = Visual Studio 2013
 ::   vc140 = Visual Studio 2015
-::   vc150 = Visual Studio 2017
+::   vc141 = Visual Studio 2017
 ::
 :: Honors any existing COMPILER environment variable
 ::   setting instead of overwriting it, to allow it
@@ -44,10 +44,10 @@
   IF !ERRORLEVEL! == 0 (SET COMPILER=vc110)
   CALL :CHECK 18
   IF !ERRORLEVEL! == 0 (SET COMPILER=vc120)
-  CALL :CHECK 19.00
+  CALL :CHECK 19.0
   IF !ERRORLEVEL! == 0 (SET COMPILER=vc140)
-  CALL :CHECK 19.10
-  IF !ERRORLEVEL! == 0 (SET COMPILER=vc150)
+  CALL :CHECK 19.1
+  IF !ERRORLEVEL! == 0 (SET COMPILER=vc141)
 )
 
 IF NOT DEFINED COMPILER (
@@ -59,5 +59,5 @@
 EXIT /B 0
 
 :CHECK
-cl /? 2>&1 | findstr /C:"Version %1%." > nul
+cl /? 2>&1 | findstr /C:"Version %1%" > nul
 EXIT /B
diff --git a/build/appveyor/cl_setenv.bat b/build/appveyor/cl_setenv.bat
index e80d6b5..c33366d 100644
--- a/build/appveyor/cl_setenv.bat
+++ b/build/appveyor/cl_setenv.bat
@@ -12,20 +12,20 @@
 :: limitations under the License.
 ::
 
-       IF "%PROFILE%" == "MSVC2010" (
-  CALL "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" %PLATFORM%
-) ELSE IF "%PROFILE%" == "MSVC2012" (
+@ECHO OFF
+
+IF "%PROFILE%" == "MSVC2012" (
   CALL "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" %PLATFORM%
 ) ELSE IF "%PROFILE%" == "MSVC2013" (
   CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" %PLATFORM%
 ) ELSE IF "%PROFILE%" == "MSVC2015" (
   CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM%
 ) ELSE IF "%PROFILE%" == "MSVC2017" (
-  CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat" %PLATFORM%
+  CALL :SETUPNEWERMSVC    || EXIT /B
 ) ELSE IF "%PROFILE%" == "MINGW" (
-  SET MSYS2_PATH_TYPE=stock
-) ELSE IF "%PROFILE%" == "MSYS" (
-  SET MSYS2_PATH_TYPE=stock
+  REM Supported, nothing special to do here.
+) ELSE IF "%PROFILE%" == "CYGWIN" (
+  REM Supported, nothing special to do here.
 ) ELSE (
   ECHO Unsupported PROFILE=%PROFILE% or PLATFORM=%PLATFORM%
   EXIT /B 1
@@ -35,58 +35,87 @@
 CALL cl_setgenerator.bat  || EXIT /B
 
 SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor
-SET BUILDCACHE=%APPVEYOR_BUILD_FOLDER%\buildcache
-SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\local-thrift-build
-SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\local-thrift-inst
+SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM%
+SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM%
 SET SRCDIR=%APPVEYOR_BUILD_FOLDER%
 
-: PLATFORM is x64 or x86, but we want x86 to become "32" when we strip it down for paths:
+:: PLATFORM is x64 or x86
+:: NORM_PLATFORM is 64 or 32
 SET NORM_PLATFORM=%PLATFORM:~-2,2%
 IF "%NORM_PLATFORM%" == "86" (SET NORM_PLATFORM=32)
 
-:: FindBoost needs forward slashes so cmake doesn't see something as an escaped character
-SET BOOST_ROOT=C:/Libraries/boost_%BOOST_VERSION:.=_%
-SET BOOST_LIBRARYDIR=%BOOST_ROOT%/lib%NORM_PLATFORM%-msvc-%COMPILER:~-3,2%.0
-SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM%
-SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty
+IF "%PROFILE:~0,4%" == "MSVC" (
 
-:: MSVC2010 doesn't "do" std::thread
-IF "%COMPILER%" == "vc100" (
-  SET THREADMODEL=BOOST
-) ELSE (
+  :: FindBoost needs forward slashes so cmake doesn't see something as an escaped character
+  SET BOOST_ROOT=C:/Libraries/boost_%BOOST_VERSION:.=_%
+  SET BOOST_LIBRARYDIR=!BOOST_ROOT!/lib%NORM_PLATFORM%-msvc-%COMPILER:~-3,2%.%COMPILER:~-1,1%
+  SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM%
+  SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty
+
   SET THREADMODEL=STD
-)
 
-IF "%PYTHON_VERSION%" == "" (
-  SET WITH_PYTHON=OFF
-) ELSE (
-  SET WITH_PYTHON=ON
-  SET PATH=C:\Python%PYTHON_VERSION:.=%\scripts;C:\Python%PYTHON_VERSION:.=%;!PATH!
-)
-IF "%CONFIGURATION%" == "Debug" (SET ZLIB_LIB_SUFFIX=d)
+  IF "%PYTHON_VERSION%" == "" (
+    SET WITH_PYTHON=OFF
+  ) ELSE (
+    SET WITH_PYTHON=ON
+    IF /i "%PLATFORM%" == "x64" SET PTEXT=-x64
+    SET PATH=C:\Python%PYTHON_VERSION:.=%!PTEXT!\scripts;C:\Python%PYTHON_VERSION:.=%!PTEXT!;!PATH!
+  )
+  IF "%CONFIGURATION%" == "Debug" (SET ZLIB_LIB_SUFFIX=d)
 
-IF NOT "%QT_VERSION%" == "" (
-  IF /i "%PLATFORM%" == "x64" SET QTEXT=_64
-  SET PATH=C:\Qt\%QT_VERSION%\%PROFILE%!QTEXT!\bin;!PATH!
-)
+  IF NOT "%QT_VERSION%" == "" (
+    IF /i "%PLATFORM%" == "x64" SET QTEXT=_64
+    SET PATH=C:\Qt\%QT_VERSION%\%PROFILE%!QTEXT!\bin;!PATH!
+  )
 
-IF NOT "%PROFILE:~0,4%" == "MSVC" (
+) ELSE IF "%PROFILE:~0,4%" == "MING" (
+
+  :: PLATFORM = x86 means MINGWPLAT i686
+  :: PLATFORM = x64 means MINGWPLAT x86_64
+  SET MINGWPLAT=x86_64
+  IF "%PLATFORM%" == "x86" (SET MINGWPLAT=i686)
 
   SET BASH=C:\msys64\usr\bin\bash.exe
-  SET BOOST_ROOT=
-  SET BOOST_INCLUDEDIR=/mingw64/include
-  SET BOOST_LIBRARYDIR=/mingw64/lib
-  SET OPENSSL_LIBRARIES=/mingw64/lib
-  SET OPENSSL_ROOT=/mingw64
-  SET WIN3P=
+  !BASH! -lc "sed -i '/export PATH=\/mingw32\/bin/d' ~/.bash_profile && sed -i '/export PATH=\/mingw64\/bin/d' ~/.bash_profile && echo 'export PATH=/mingw%NORM_PLATFORM%/bin:$PATH' >> ~/.bash_profile" || EXIT /B
 
-  !BASH! -lc "sed -i '/export PATH=\/mingw64\/bin/d' ~/.bash_profile && echo 'export PATH=/mingw64/bin:$PATH' >> ~/.bash_profile" || EXIT /B
+  SET BUILDDIR=%BUILDDIR:\=/%
+  SET BUILDDIR=/c!BUILDDIR:~2!
+  SET INSTDIR=%INSTDIR:\=/%
+  SET INSTDIR=/c!INSTDIR:~2!
+  SET SRCDIR=%SRCDIR:\=/%
+  SET SRCDIR=/c!SRCDIR:~2!
+
+) ELSE IF "%PROFILE:~0,4%" == "CYGW" (
+
+  SET CYGWINROOT=C:\cygwin
+  IF "%PLATFORM%" == "x64" (SET CYGWINROOT=!CYGWINROOT!64)
+
+  SET BASH=!CYGWINROOT!\bin\bash.exe
+  SET SETUP=!CYGWINROOT!\setup-x86
+  IF "%PLATFORM%" == "x64" (SET SETUP=!SETUP!_64)
+  SET SETUP=!SETUP!.exe
+
+  SET BUILDDIR=%BUILDDIR:\=/%
+  SET BUILDDIR=/cygdrive/c!BUILDDIR:~2!
+  SET INSTDIR=%INSTDIR:\=/%
+  SET INSTDIR_CYG=/cygdrive/c!INSTDIR:~2!
+  SET SRCDIR=%SRCDIR:\=/%
+  SET SRCDIR=/cygdrive/c!SRCDIR:~2!
 
 )
 
-SET BUILDDIR_MSYS=%BUILDDIR:\=/%
-SET BUILDDIR_MSYS=/c%BUILDDIR_MSYS:~2%
-SET INSTDIR_MSYS=%INSTDIR:\=/%
-SET INSTDIR_MSYS=/c%INSTDIR_MSYS:~2%
-SET SRCDIR_MSYS=%SRCDIR:\=/%
-SET SRCDIR_MSYS=/c%SRCDIR_MSYS:~2%
+GOTO :EOF
+
+:SETUPNEWERMSVC
+  FOR /F "USEBACKQ TOKENS=*" %%i IN (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[15.0,16.0)" -property installationPath`) DO (
+    IF "%MSVCROOT%" == "" (SET MSVCROOT=%%i)
+  )
+  SET MSVCPLAT=x86
+  IF "%PLATFORM%" == "x64" (SET MSVCPLAT=amd64)
+
+  SET CURRENTDIR=%CD%
+  CALL "!MSVCROOT!\Common7\Tools\VsDevCmd.bat" -arch=!MSVCPLAT! || EXIT /B
+  CD %CURRENTDIR%
+  EXIT /B
+
+:EOF
diff --git a/build/appveyor/cl_setgenerator.bat b/build/appveyor/cl_setgenerator.bat
index 7ca9853..5eb6ff3 100644
--- a/build/appveyor/cl_setgenerator.bat
+++ b/build/appveyor/cl_setgenerator.bat
@@ -28,6 +28,7 @@
 ::                                 Optional [arch] can be "Win64" or "IA64".
 ::  MinGW Makefiles              = Generates makefiles for MinGW
 ::  MSYS Makefiles               = Generates makefiles for MSYS
+::  Unix Makefiles               = Generates makefiles for CYGWIN
 ::
 :: Honors any existing GENERATOR environment variable
 ::   setting instead of overwriting it, to allow it
@@ -45,6 +46,10 @@
 
 IF "%PROFILE:~0,4%" == "MING" (
   SET GENERATOR=MinGW Makefiles
+
+) ELSE IF "%PROFILE:~0,4%" == "CYGW" (
+  SET GENERATOR=Unix Makefiles
+
 ) ELSE IF "%PROFILE:~0,4%" == "MSYS" (
   SET GENERATOR=MSYS Makefiles
 ) ELSE (
@@ -55,9 +60,9 @@
   IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 11 2012!GENARCH!
   CALL :CHECK 18
   IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 12 2013!GENARCH!
-  CALL :CHECK 19.00
+  CALL :CHECK 19.0
   IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 14 2015!GENARCH!
-  CALL :CHECK 19.10
+  CALL :CHECK 19.1
   IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 15 2017!GENARCH!
 )
 
@@ -70,5 +75,5 @@
 EXIT /B 0
 
 :CHECK
-cl /? 2>&1 | findstr /C:"Version %1%." > nul
+cl /? 2>&1 | findstr /C:"Version %1%" > nul
 EXIT /B
diff --git a/build/appveyor/cl_showenv.bat b/build/appveyor/cl_showenv.bat
index 33dd660..a70a490 100644
--- a/build/appveyor/cl_showenv.bat
+++ b/build/appveyor/cl_showenv.bat
@@ -34,30 +34,26 @@
 ECHO Our Variables
 ECHO -------------------------------------------------------------------------------
 ECHO APPVEYOR_SCRIPTS      = %APPVEYOR_SCRIPTS%
+ECHO BASH                  = %BASH%
 ECHO BOOST_ROOT            = %BOOST_ROOT%
 ECHO BOOST_INCLUDEDIR      = %BOOST_INCLUDEDIR%
 ECHO BOOST_LIBRARYDIR      = %BOOST_LIBRARYDIR%
-ECHO BUILDCACHE            = %BUILDCACHE%
 ECHO BUILDDIR              = %BUILDDIR%
 ECHO COMPILER              = %COMPILER%
 ECHO GENERATOR             = %GENERATOR%
 ECHO INSTDIR               = %INSTDIR%
 ECHO JAVA_HOME             = %JAVA_HOME%
 ECHO OPENSSL_ROOT          = %OPENSSL_ROOT%
+ECHO SETUP                 = %SETUP%
 ECHO SRCDIR                = %SRCDIR%
 ECHO WIN3P                 = %WIN3P%
 ECHO WITH_PYTHON           = %WITH_PYTHON%
 ECHO ZLIB_STATIC_SUFFIX    = %ZLIB_STATIC_SUFFIX%
 IF NOT "%PROFILE:~0,4%" == "MSVC" (
-ECHO/
-ECHO MSYS2/MinGW
-ECHO -------------------------------------------------------------------------------
-ECHO BUILDDIR_MSYS         = %BUILDDIR_MSYS%
-ECHO INSTDIR_MSYS          = %INSTDIR_MSYS%
-ECHO MSYS2_PATH_TYPE       = %MSYS2_PATH_TYPE%
-ECHO SRCDIR_MSYS           = %SRCDIR_MSYS%
-ECHO PATH                  =
-C:\msys64\usr\bin\bash -lc "echo $PATH"
+  ECHO/
+  ECHO UNIXy PATH
+  ECHO -------------------------------------------------------------------------------
+  %BASH% -lc "echo $PATH"
 )
 ECHO/
 ECHO Windows PATH
diff --git a/build/appveyor/simulate-appveyor.bat b/build/appveyor/simulate-appveyor.bat
index b32c0da..8674f40 100644
--- a/build/appveyor/simulate-appveyor.bat
+++ b/build/appveyor/simulate-appveyor.bat
@@ -16,7 +16,7 @@
 :: Helps build thrift by pretending to be appveyor
 :: Usage:
 ::   cd build\appveyor
-::   simulate-appveyor.bat [Debug|Release] [x86|x64] [MINGW|MSVC2015]
+::   simulate-appveyor.bat [Debug|Release] [x86|x64] [CYGWIN|MINGW|MSVC201?]
 ::
 
 @ECHO OFF
diff --git a/build/cmake/ConfigureChecks.cmake b/build/cmake/ConfigureChecks.cmake
index 12a50df..457bfe0 100644
--- a/build/cmake/ConfigureChecks.cmake
+++ b/build/cmake/ConfigureChecks.cmake
@@ -34,15 +34,18 @@
 check_include_file(inttypes.h HAVE_INTTYPES_H)
 check_include_file(netdb.h HAVE_NETDB_H)
 check_include_file(netinet/in.h HAVE_NETINET_IN_H)
+check_include_file(signal.h HAVE_SIGNAL_H)
 check_include_file(stdint.h HAVE_STDINT_H)
 check_include_file(unistd.h HAVE_UNISTD_H)
 check_include_file(pthread.h HAVE_PTHREAD_H)
-check_include_file(sys/time.h HAVE_SYS_TIME_H)
+check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H)
 check_include_file(sys/param.h HAVE_SYS_PARAM_H)
 check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
 check_include_file(sys/socket.h HAVE_SYS_SOCKET_H)
 check_include_file(sys/stat.h HAVE_SYS_STAT_H)
+check_include_file(sys/time.h HAVE_SYS_TIME_H)
 check_include_file(sys/un.h HAVE_SYS_UN_H)
+check_include_file(poll.h HAVE_POLL_H)
 check_include_file(sys/poll.h HAVE_SYS_POLL_H)
 check_include_file(sys/select.h HAVE_SYS_SELECT_H)
 check_include_file(sched.h HAVE_SCHED_H)
diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake
index bb32399..93255e0 100644
--- a/build/cmake/DefineCMakeDefaults.cmake
+++ b/build/cmake/DefineCMakeDefaults.cmake
@@ -35,7 +35,7 @@
 set(CMAKE_COLOR_MAKEFILE ON)
 
 # Define the generic version of the libraries here
-set(GENERIC_LIB_VERSION "0.11.0")
+set(GENERIC_LIB_VERSION "1.0.0")
 set(GENERIC_LIB_SOVERSION "0")
 
 # Set the default build type to release with debug info
@@ -73,19 +73,16 @@
 # C++ Language Level Defaults - this depends on the compiler capabilities
 #
 if (NOT DEFINED CMAKE_CXX_STANDARD)
-  if (MSVC AND MSVC_VERSION LESS 1800)
-    # MSVC 2012 and earlier don't support template aliases so you have to use C++98
-    set(CMAKE_CXX_STANDARD 98) 
-    message(STATUS "Setting C++98 as the default language level (for an older MSVC compiler).")
-  else()
-    set(CMAKE_CXX_STANDARD 11) # C++11
-    message(STATUS "Setting C++11 as the default language level.")
-  endif()
+  set(CMAKE_CXX_STANDARD 11) # C++11
+  message(STATUS "Setting C++11 as the default language level.")
   message(STATUS "To specify a different C++ language level, set CMAKE_CXX_STANDARD")
 endif()
 
-if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
-  set(CMAKE_CXX_STANDARD_REQUIRED OFF) # can degrade to C++98 if compiler does not support C++11
+if (CMAKE_CXX_STANDARD EQUAL 98)
+  message(FATAL_ERROR "only C++11 or above C++ standard is supported")
+elseif (CMAKE_CXX_STANDARD EQUAL 11)
+  # should not fallback to C++98
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
 endif()
 
 if (NOT DEFINED CMAKE_CXX_EXTENSIONS)
diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake
index f1ea7bb..9aff53c 100644
--- a/build/cmake/DefineOptions.cmake
+++ b/build/cmake/DefineOptions.cmake
@@ -40,16 +40,6 @@
 # and enables the library if all are found. This means the default is to build as
 # much as possible but leaving out libraries if their dependencies are not met.
 
-option(WITH_BOOST_FUNCTIONAL "Use boost/tr1/functional.hpp even under C++11 or later" OFF)
-if (WITH_BOOST_FUNCTIONAL)
-    add_definitions(-DFORCE_BOOST_FUNCTIONAL)
-endif()
-
-option(WITH_BOOST_SMART_PTR "Use boost/smart_ptr.hpp even under C++11 or later" OFF)
-if (WITH_BOOST_SMART_PTR)
-    add_definitions(-DFORCE_BOOST_SMART_PTR)
-endif()
-
 option(WITH_BOOST_STATIC "Build with Boost static link library" OFF)
 set(Boost_USE_STATIC_LIBS ${WITH_BOOST_STATIC})
 if (NOT WITH_BOOST_STATIC)
@@ -88,9 +78,7 @@
     find_package(OpenSSL QUIET)
     CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON
                            "OPENSSL_FOUND" OFF)
-    option(WITH_STDTHREADS "Build with C++ std::thread support" OFF)
-    CMAKE_DEPENDENT_OPTION(WITH_BOOSTTHREADS "Build with Boost threads support" OFF
-        "NOT WITH_STDTHREADS;Boost_FOUND" OFF)
+    option(WITH_STDTHREADS "Build with C++ std::thread support" ON)
 endif()
 CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON
                        "BUILD_LIBRARIES;WITH_CPP;Boost_FOUND" OFF)
@@ -107,7 +95,7 @@
 
 if(BUILD_CPP)
     set(boost_components)
-    if(WITH_BOOSTTHREADS OR BUILD_TESTING)
+    if(BUILD_TESTING)
         list(APPEND boost_components system thread)
     endif()
     if(BUILD_TESTING)
@@ -127,10 +115,10 @@
     CMAKE_DEPENDENT_OPTION(BUILD_JAVA "Build Java library" ON
                            "BUILD_LIBRARIES;WITH_JAVA;GRADLE_FOUND" OFF)
 else()
+    find_package(Gradlew QUIET)
     find_package(Java QUIET)
-    find_package(Ant QUIET)
     CMAKE_DEPENDENT_OPTION(BUILD_JAVA "Build Java library" ON
-                           "BUILD_LIBRARIES;WITH_JAVA;JAVA_FOUND;ANT_FOUND" OFF)
+                           "BUILD_LIBRARIES;WITH_JAVA;JAVA_FOUND;GRADLEW_FOUND" OFF)
 endif()
 
 # Python
@@ -193,7 +181,7 @@
     MESSAGE_DEP(GRADLE_FOUND "Gradle missing")
 else()
     MESSAGE_DEP(JAVA_FOUND "Java Runtime missing")
-    MESSAGE_DEP(ANT_FOUND "Ant missing")
+    MESSAGE_DEP(GRADLEW_FOUND "Gradle Wrapper missing")
 endif()
 message(STATUS "  Build Python library:                       ${BUILD_PYTHON}")
 MESSAGE_DEP(WITH_PYTHON "Disabled by WITH_PYTHON=OFF")
@@ -206,9 +194,6 @@
 message(STATUS "  Build shared libraries:                     ${WITH_SHARED_LIB}")
 message(STATUS "  Build static libraries:                     ${WITH_STATIC_LIB}")
 message(STATUS "  Build with Boost static link library:       ${WITH_BOOST_STATIC}")
-message(STATUS "  Build with Boost thread support:            ${WITH_BOOSTTHREADS}")
-message(STATUS "  Build with boost/tr1/functional (forced)    ${WITH_BOOST_FUNCTIONAL}")
-message(STATUS "  Build with boost/smart_ptr (forced)         ${WITH_BOOST_SMART_PTR}")
 message(STATUS "  Build with C++ std::thread support:         ${WITH_STDTHREADS}")
 message(STATUS "  Build with libevent support:                ${WITH_LIBEVENT}")
 message(STATUS "  Build with OpenSSL support:                 ${WITH_OPENSSL}")
diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake
index f443489..3f112b6 100644
--- a/build/cmake/DefinePlatformSpecifc.cmake
+++ b/build/cmake/DefinePlatformSpecifc.cmake
@@ -61,9 +61,6 @@
         set(STATIC_POSTFIX "md" CACHE STRING "Set static library postfix" FORCE)
     endif(WITH_MT)
 
-    # Disable Windows.h definition of macros for min and max
-    add_definitions("-DNOMINMAX")
-
     # Disable boost auto linking pragmas - cmake includes the right files
     add_definitions("-DBOOST_ALL_NO_LIB")
 
@@ -90,11 +87,10 @@
 endif()
 
 add_definitions("-D__STDC_FORMAT_MACROS")
+add_definitions("-D__STDC_LIMIT_MACROS")
 
 # WITH_*THREADS selects which threading library to use
-if(WITH_BOOSTTHREADS)
-  add_definitions("-DUSE_BOOST_THREAD=1")
-elseif(WITH_STDTHREADS)
+if(WITH_STDTHREADS)
   add_definitions("-DUSE_STD_THREAD=1")
 endif()
 
@@ -107,13 +103,6 @@
 endif()
 if (CMAKE_CXX_EXTENSIONS)
   string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [with compiler-specific extensions]")
-else()
-  if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros -Wno-long-long")
-  endif()
-  if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-long-long")
-  endif()
 endif()
 
 if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
@@ -125,7 +114,5 @@
   if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8")
     message(SEND_ERROR "Thrift compiler plug-in support is not possible with older gcc ( < 4.8 ) compiler")
   endif()
-  message(STATUS "Forcing use of boost::smart_ptr to build WITH_PLUGIN")
-  add_definitions("-DFORCE_BOOST_SMART_PTR=1")
 endif()
 
diff --git a/build/cmake/FindGradlew.cmake b/build/cmake/FindGradlew.cmake
new file mode 100644
index 0000000..17bb998
--- /dev/null
+++ b/build/cmake/FindGradlew.cmake
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+
+#  GRADLEW_FOUND - system has Gradlew
+#  GRADLEW_EXECUTABLE - the Gradlew executable
+#
+# It will search the location CMAKE_SOURCE_DIR/lib/java
+
+include(FindPackageHandleStandardArgs)
+
+find_program(GRADLEW_EXECUTABLE gradlew PATHS ${CMAKE_SOURCE_DIR}/lib/java NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+find_package_handle_standard_args(Gradlew DEFAULT_MSG GRADLEW_EXECUTABLE)
+mark_as_advanced(GRADLEW_EXECUTABLE)
+
+# Buggy find_program cannot find gradlew.bat when gradlew is at the same path
+# and even buggier ctest will not execute gradlew.bat when gradlew is given.
+if(CMAKE_HOST_WIN32)
+    string(REGEX REPLACE "(.+gradlew)$" "\\1.bat" GRADLEW_EXECUTABLE ${GRADLEW_EXECUTABLE})
+endif(CMAKE_HOST_WIN32)
diff --git a/build/cmake/README-MSYS2.md b/build/cmake/README-MSYS2.md
index 02679e6..07cad92 100644
--- a/build/cmake/README-MSYS2.md
+++ b/build/cmake/README-MSYS2.md
@@ -43,7 +43,7 @@
     cmake -G"MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make \
        -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc.exe \
        -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe \
-       -DWITH_BOOSTTHREADS=ON -DWITH_LIBEVENT=OFF \
+       -DWITH_LIBEVENT=OFF \
        -DWITH_SHARED_LIB=OFF -DWITH_STATIC_LIB=ON \
        -DWITH_JAVA=OFF -DWITH_PYTHON=OFF -DWITH_PERL=OFF \
        ../thrift
diff --git a/build/cmake/README.md b/build/cmake/README.md
index ebc4f7d..e5c128b 100644
--- a/build/cmake/README.md
+++ b/build/cmake/README.md
@@ -30,7 +30,7 @@
     cmake -G "Visual Studio 12 2013 Win64" \
     -DBOOST_ROOT=C:/3rdparty/boost_1_58_0 \
     -DZLIB_ROOT=C:/3rdparty/zlib128-dll \
-    -DWITH_SHARED_LIB=off -DWITH_BOOSTTHREADS=ON ..
+    -DWITH_SHARED_LIB=off ..
 
 and open the development environment you like with the solution or do this:
 
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index 083bc55..5f0ae46 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -64,9 +64,6 @@
    see: aclocal/ac_prog_bison.m4 */
 #cmakedefine BISON_USE_PARSER_H_EXTENSION 1
 
-/* replaces POSIX pthread by boost::thread */
-#cmakedefine USE_BOOST_THREAD 1
-
 /* replaces POSIX pthread by std::thread */
 #cmakedefine USE_STD_THREAD 1
 
@@ -91,6 +88,9 @@
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #cmakedefine HAVE_NETINET_IN_H 1
 
+/* Define to 1 if you have the <signal.h> header file. */
+#cmakedefine HAVE_SIGNAL_H 1
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #cmakedefine HAVE_STDINT_H 1
 
@@ -100,8 +100,8 @@
 /* Define to 1 if you have the <pthread.h> header file. */
 #cmakedefine HAVE_PTHREAD_H 1
 
-/* Define to 1 if you have the <sys/time.h> header file. */
-#cmakedefine HAVE_SYS_TIME_H 1
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#cmakedefine HAVE_SYS_IOCTL_H 1
 
 /* Define to 1 if you have the <sys/param.h> header file. */
 #cmakedefine HAVE_SYS_PARAM_H 1
@@ -118,12 +118,18 @@
 /* Define to 1 if you have the <sys/un.h> header file. */
 #cmakedefine HAVE_SYS_UN_H 1
 
+/* Define to 1 if you have the <poll.h> header file. */
+#cmakedefine HAVE_POLL_H 1
+
 /* Define to 1 if you have the <sys/poll.h> header file. */
 #cmakedefine HAVE_SYS_POLL_H 1
 
 /* Define to 1 if you have the <sys/select.h> header file. */
 #cmakedefine HAVE_SYS_SELECT_H 1
 
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H 1
+
 /* Define to 1 if you have the <sched.h> header file. */
 #cmakedefine HAVE_SCHED_H 1
 
diff --git a/build/docker/README.md b/build/docker/README.md
index a8d9501..966d690 100644
--- a/build/docker/README.md
+++ b/build/docker/README.md
@@ -1,43 +1,65 @@
 # Docker Integration #
 
-Due to the large number of language requirements to build Apache Thrift, docker containers are used to build and test the project on a variety of platforms to provide maximum test coverage.
+Due to the large number of languages supported by Apache Thrift,
+docker containers are used to build and test the project on a
+variety of platforms to provide maximum test coverage.
+
+## Appveyor Integration ##
+
+At this time the Appveyor scripts do not use docker containers.
+Once Microsoft supports Visual Studio Build Tools running inside
+nano containers (instead of Core, which is huge) then we will
+consider using containers for the Windows builds as well.
 
 ## Travis CI Integration ##
 
-The Travis CI scripts use the following environment variables and logic to determine their behavior.
+The Travis CI scripts use the following environment variables and
+logic to determine their behavior:
 
 ### Environment Variables ###
 
 | Variable | Default | Usage |
 | -------- | ----- | ------- |
-| `DISTRO` | `ubuntu-xenial` | Set by various build jobs in `.travis.yml` to run builds in different containers.  Not intended to be set externally.|
+| `DISTRO` | `ubuntu-bionic` | Set by various build jobs in `.travis.yml` to run builds in different containers.  Not intended to be set externally.|
 | `DOCKER_REPO` | `thrift/thrift-build` | The name of the Docker Hub repository to obtain and store docker images. |
 | `DOCKER_USER` | `<none>` | The Docker Hub account name containing the repository. |
 | `DOCKER_PASS` | `<none>` | The Docker Hub account password to use when pushing new tags. |
 
-For example, the default docker image that is used in builds if no overrides are specified would be: `thrift/thrift-build:ubuntu-xenial`
+For example, the default docker image that is used in builds if no overrides are specified would be: `thrift/thrift-build:ubuntu-bionic`
 
 ### Forks ###
 
-If you have forked the Apache Thrift repository and you would like to use your own Docker Hub account to store thrift build images, you can use the Travis CI web interface to set the `DOCKER_USER`, `DOCKER_PASS`, and `DOCKER_REPO` variables in a secure manner.  Your fork builds will then pull, push, and tag the docker images in your account.
+If you have forked the Apache Thrift repository and you would like
+to use your own Docker Hub account to store thrift build images,
+you can use the Travis CI web interface to set the `DOCKER_USER`,
+`DOCKER_PASS`, and `DOCKER_REPO` variables in a secure manner.
+Your fork builds will then pull, push, and tag the docker images
+in your account.
 
 ### Logic ###
 
-The Travis CI build runs in two phases - first the docker images are rebuilt for each of the three supported containers if they do not match the Dockerfile that was used to build the most recent tag.  If a `DOCKER_PASS` environment variable is specified, the docker stage builds will attempt to log into Docker Hub and push the resulting tags.
+The Travis CI build runs in two phases - first the docker images are rebuilt
+for each of the supported containers if they do not match the Dockerfile that
+was used to build the most recent tag.  If a `DOCKER_PASS` environment
+variable is specified, the docker stage builds will attempt to log into
+Docker Hub and push the resulting tags.
 
 ## Supported Containers ##
 
-The Travis CI (continuous integration) builds use the Ubuntu Trusty, Xenial, and Artful images to maximize language level coverage.
+The Travis CI (continuous integration) builds use the Ubuntu Bionic
+(18.04 LTS) and Xenial (16.04 LTS) images to maximize language level
+coverage.
 
 ### Ubuntu ###
 
-* trusty (legacy)
-* xenial (stable)
-* artful (latest)
+* bionic (stable, current)
+* artful (previous stable)
+* xenial (legacy)
 
 ## Unsupported Containers ##
 
 These containers may be in various states, and may not build everything.
+They can be found in the `old/` subdirectory.
 
 ### CentOS ###
 * 7.3
@@ -51,7 +73,9 @@
 
 ## Building like Travis CI does, locally ##
 
-We recommend you build locally the same way Travis CI does, so that when you submit your pull request you will run into fewer surprises.  To make it a little easier, put the following into your `~/.bash_aliases` file:
+We recommend you build locally the same way Travis CI does, so that when you
+submit your pull request you will run into fewer surprises.  To make it a
+little easier, put the following into your `~/.bash_aliases` file:
 
     # Kill all running containers.
     alias dockerkillall='docker kill $(docker ps -q)'
@@ -77,27 +101,34 @@
       docker run -v $(pwd):/thrift/src -it $1 /bin/bash
     }
 
-To pull down the current image being used to build (the same way Travis CI does it) - if it is out of date in any way it will build a new one for you:
+Then, to pull down the current image being used to build (the same way
+Travis CI does it) - if it is out of date in any way it will build a
+new one for you:
 
-    thrift$ DOCKER_REPO=thrift/thrift-build DISTRO=ubuntu-xenial build/docker/refresh.sh
+    thrift$ DOCKER_REPO=thrift/thrift-build DISTRO=ubuntu-bionic build/docker/refresh.sh
 
-To run all unit tests (just like Travis CI):
+To run all unit tests (just like Travis CI does):
 
-    thrift$ dockerrun ubuntu-xenial
+    thrift$ dockerrun ubuntu-bionic
     root@8caf56b0ce7b:/thrift/src# build/docker/scripts/autotools.sh
 
-To run the cross tests (just like Travis CI):
+To run the cross tests (just like Travis CI does):
 
-    thrift$ dockerrun ubuntu-xenial
+    thrift$ dockerrun ubuntu-bionic
     root@8caf56b0ce7b:/thrift/src# build/docker/scripts/cross-test.sh
 
 When you are done, you want to clean up occasionally so that docker isn't using lots of extra disk space:
 
     thrift$ dockerclean
 
-You need to run the docker commands from the root of the git repository for them to work.
+You need to run the docker commands from the root of the local clone of the
+thrift git repository for them to work.
 
-When you are done in the root docker shell you can `exit` to go back to your user host shell.  Once the unit tests and cross test passes locally, then submit he changes, and squash the pull request to one commit to make it easier to merge.  Thanks.  I am going to update the docker README.md with this information so others can leverage it too.  Now you are building like Travis CI does!
+When you are done in the root docker shell you can `exit` to go back to
+your user host shell.  Once the unit tests and cross test passes locally,
+submit the changes, and if desired squash the pull request to one commit
+to make it easier to merge (the committers can squash at commit time now
+that GitHub is the master repository).  Now you are building like Travis CI does!
 
 ## Raw Commands for Building with Docker ##
 
@@ -105,7 +136,7 @@
 
 Build the image:
 
-    thrift$ docker build -t thrift build/docker/ubuntu-xenial
+    thrift$ docker build -t thrift build/docker/ubuntu-bionic
 
 Open a command prompt in the image:
 
@@ -115,54 +146,53 @@
 
 Last updated: October 1, 2017
 
-| Tool      | ubuntu-trusty | ubuntu-xenial | ubuntu-artful | Notes |
-| :-------- | :------------ | :------------ | :------------ | :---- |
-| ant       | 1.9.3         | 1.9.6         | 1.9.9         |       |
-| autoconf  | 2.69          | 2.69          | 2.69          |       |
-| automake  | 1.14.1        | 1.15          | 1.15          |       |
-| bison     | 3.0.2         | 3.0.4         | 3.0.4         |       |
-| boost     | 1.54.0        | 1.58.0        | 1.63.0        | artful: stock boost 1.62.0 has problems running unit tests |
-| cmake     | 3.2.2         | 3.5.1         | 3.9.1         |       |
-| cppcheck  | 1.61          | 1.72          | 1.80          |       |
-| flex      | 2.5.35        | 2.6.0         | 2.6.1         |       |
-| glibc     | 2.19          | 2.23          | 2.26          |       |
-| libevent  | 2.0.21        | 2.0.21        | 2.1           |       |
-| libstdc++ | 4.8.4         | 5.4.0         | 7.2.0         |       |
-| make      | 3.81          | 4.1           | 4.1           |       |
-| openssl   | 1.0.1f        | 1.0.2g        | 1.0.2g        |       |
-| qt5       | 5.2.1         | 5.5.1         | 5.9.1         |       |
+| Tool      | ubuntu-xenial | ubuntu-bionic | Notes |
+| :-------- | :------------ | :------------ | :---- |
+| ant       | 1.9.6         | 1.10.3        |       |
+| autoconf  | 2.69          | 2.69          |       |
+| automake  | 1.15          | 1.15.1        |       |
+| bison     | 3.0.4         | 3.0.4         |       |
+| boost     | 1.58.0        | 1.65.1        |       |
+| cmake     | 3.5.1         | 3.10.2        |       |
+| cppcheck  | 1.72          | 1.82          |       |
+| flex      | 2.6.0         | 2.6.4         |       |
+| libc6     | 2.23          | 2.27          | glibc |
+| libevent  | 2.0.21        | 2.1.8         |       |
+| libstdc++ | 5.4.0         | 7.3.0         |       |
+| make      | 4.1           | 4.1           |       |
+| openssl   | 1.0.2g        | 1.1.0g        |       |
+| qt5       | 5.5.1         | 5.9.5         |       |
 
 ## Compiler/Language Versions per Dockerfile ##
 
-Last updated: October 1, 2017
-
-| Language  | ubuntu-trusty | ubuntu-xenial | ubuntu-artful | Notes |
-| :-------- | :------------ | :------------ | :------------ | :---- |
-| as3       |               |               |               | Not in CI |
-| C++ gcc   | 4.8.4         | 5.4.0         | 7.2.0         |       |
-| C++ clang | 3.4           | 3.8           | 4.0           |       |
-| C# (mono) | 3.2.8.0       | 4.2.1         | 4.6.2.7       |       |
-| c_glib    | 2.40.2        | 2.48.2        | 2.54.0        |       |
-| cocoa     |               |               |               | Not in CI |
-| d         | 2.070.2       | 2.073.2       | 2.076.0       |       |
-| dart      | 1.20.1        | 1.24.2        | 1.24.2        |       |
-| delphi    |               |               |               | Not in CI |
-| dotnet    |               | 2.0.3         | 2.0.3         |       |
-| erlang    | R16B03        | 18.3          | 20.0.4        |       |
-| go        | 1.2.1         | 1.6.2         | 1.8.3         |       |
-| haskell   | 7.6.3         | 7.10.3        | 8.0.2         |       |
-| haxe      |               | 3.2.1         | 3.4.2         | disabled in trusty builds - cores on install v3.0.0, disabled in artful builds - see THRIFT-4352 |
-| java      | 1.7.0_151     | 1.8.0_131     | 1.8.0_151     |       |
-| js        |               |               |               | Unsure how to look for version info? |
-| lua       | 5.1.5         | 5.2.4         | 5.2.4         | Lua 5.3: see THRIFT-4386 |
-| nodejs    |               | 4.2.6         | 8.9.1         | trusty has node.js 0.10.0 which is too old |
-| ocaml     |               | 4.02.3        | 4.04.0        |       |
-| perl      | 5.18.2        | 5.22.1        | 5.26.0        |       |
-| php       | 5.5.9         | 7.0.22        | 7.1.8         |       |
-| python    | 2.7.6         | 2.7.12        | 2.7.14        |       |
-| python3   | 3.4.3         | 3.5.2         | 3.6.3         |       |
-| ruby      | 1.9.3p484     | 2.3.1p112     | 2.3.3p222     |       |
-| rust      | 1.15.1        | 1.15.1        | 1.18.0        |       |
-| smalltalk |               |               |               | Not in CI |
-| swift     |               |               |               | Not in CI |
-
+| Language  | ubuntu-xenial | ubuntu-bionic | Notes |
+| :-------- | :------------ | :------------ | :---- |
+| as of     | Mar 06, 2018  | Jan 4, 2019   |       |
+| as3       |               |               | Not in CI |
+| C++ gcc   | 5.4.0         | 7.3.0         |       |
+| C++ clang | 3.8           | 6.0           |       |
+| C# (mono) | 4.2.1.0       | 4.6.2.7       |       |
+| c_glib    | 2.48.2        | 2.56.0        |       |
+| cl (sbcl) |               | 1.4.15        |       |
+| cocoa     |               |               | Not in CI |
+| d         | 2.075.1       | 2.083.1       |       |
+| dart      | 1.22.1        | 1.24.3        |       |
+| delphi    |               |               | Not in CI |
+| dotnet    | 2.1.4         | 2.2.101       |       |
+| erlang    | 18.3          | 20.2.2        |       |
+| go        | 1.7.6         | 1.11.4        |       |
+| haskell   | 7.10.3        | 8.0.2         |       |
+| haxe      | 3.2.1         | 3.4.4         | THRIFT-4352: avoid 3.4.2 |
+| java      | 1.8.0_151     | 1.8.0_191     |       |
+| js        |               |               | Unsure how to look for version info? |
+| lua       | 5.2.4         | 5.2.4         | Lua 5.3: see THRIFT-4386 |
+| nodejs    | 6.13.0        | 8.15.0        |       |
+| ocaml     |               | 4.05.0        | THRIFT-4517: ocaml 4.02.3 on xenial appears broken |
+| perl      | 5.22.1        | 5.26.1        |       |
+| php       | 7.0.22        | 7.2.10        |       |
+| python    | 2.7.12        | 2.7.15rc1     |       |
+| python3   | 3.5.2         | 3.6.7         |       |
+| ruby      | 2.3.1p112     | 2.5.1p57      |       |
+| rust      | 1.17.0        | 1.30.0        |       |
+| smalltalk |               |               | Not in CI |
+| swift     |               | 4.2.1         |       |
diff --git a/build/docker/Vagrantfile b/build/docker/old/Vagrantfile
similarity index 100%
rename from build/docker/Vagrantfile
rename to build/docker/old/Vagrantfile
diff --git a/build/docker/centos-7.3/Dockerfile b/build/docker/old/centos-7.3/Dockerfile
similarity index 100%
rename from build/docker/centos-7.3/Dockerfile
rename to build/docker/old/centos-7.3/Dockerfile
diff --git a/build/docker/debian-jessie/Dockerfile b/build/docker/old/debian-jessie/Dockerfile
similarity index 99%
rename from build/docker/debian-jessie/Dockerfile
rename to build/docker/old/debian-jessie/Dockerfile
index 7bc74fc..941b4bb 100644
--- a/build/docker/debian-jessie/Dockerfile
+++ b/build/docker/old/debian-jessie/Dockerfile
@@ -79,6 +79,7 @@
 RUN apt-get install -y --no-install-recommends \
 `# Ruby dependencies` \
       ruby \
+      ruby-bundler \
       ruby-dev \
 `# Perl dependencies` \
       libbit-vector-perl \
diff --git a/build/docker/debian-stretch/Dockerfile b/build/docker/old/debian-stretch/Dockerfile
similarity index 100%
rename from build/docker/debian-stretch/Dockerfile
rename to build/docker/old/debian-stretch/Dockerfile
diff --git a/build/docker/ubuntu-trusty/Dockerfile b/build/docker/old/ubuntu-trusty/Dockerfile
similarity index 68%
rename from build/docker/ubuntu-trusty/Dockerfile
rename to build/docker/old/ubuntu-trusty/Dockerfile
index db2041a..a8e4d3b 100644
--- a/build/docker/ubuntu-trusty/Dockerfile
+++ b/build/docker/old/ubuntu-trusty/Dockerfile
@@ -25,8 +25,10 @@
 MAINTAINER Apache Thrift <dev@thrift.apache.org>
 ENV DEBIAN_FRONTEND noninteractive
 
-RUN apt-get update && \ 
-    apt-get dist-upgrade -y && \ 
+### Add apt repos
+
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
     apt-get install -y --no-install-recommends \
       apt \
       apt-transport-https \
@@ -36,6 +38,16 @@
       software-properties-common \
       wget
 
+# D
+RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \
+        wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \
+        wget -qO - https://dlang.org/d-keyring.gpg | apt-key add -
+
+# Dart
+RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
+        curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
+          /etc/apt/sources.list.d/dart_stable.list
+
 RUN apt-get update && apt-get install -y --no-install-recommends \
 `# General dependencies` \
       bash-completion \
@@ -66,11 +78,7 @@
 `# csharp (mono) dependencies` \
       mono-devel
 
-RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \
-    wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \
-    wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - && \
-    apt-get update && \
-    apt-get install -y --no-install-recommends \
+RUN apt-get install -y --no-install-recommends \
 `# D dependencies` \
       dmd-bin=2.070.2-0 \
       libphobos2-dev=2.070.2-0 \
@@ -78,20 +86,17 @@
       dfmt \
       dscanner \
       xdg-utils
-# RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
-#     curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
-#     mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf libevent-master
-# RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
-#     mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf openssl-master
+RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
+    curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
+    mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf libevent-master
+RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
+    mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf openssl-master
 
-RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
-    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \
-    apt-get update && \
-    apt-get install -y --no-install-recommends \
+RUN apt-get install -y --no-install-recommends \
 `# Dart dependencies` \
       dart=1.20.1-1
 ENV PATH /usr/lib/dart/bin:$PATH
@@ -108,9 +113,15 @@
 `# GlibC dependencies` \
       libglib2.0-dev
 
-RUN apt-get install -y --no-install-recommends \
-`# golang (go) dependencies` \
-      golang-go
+# golang
+ENV GOLANG_VERSION 1.7.6
+ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
+ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea
+RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
+      echo "$GOLANG_DOWNLOAD_SHA256  golang.tar.gz" | sha256sum -c - && \
+      tar -C /usr/local -xzf golang.tar.gz && \
+      ln -s /usr/local/go/bin/go /usr/local/bin && \
+      rm golang.tar.gz
 
 RUN apt-get install -y --no-install-recommends \
 `# Haskell dependencies` \
@@ -166,8 +177,8 @@
       php5-cli \
       php5-dev \
       php-pear \
-      re2c \
-      phpunit
+      re2c && \
+      wget https://getcomposer.org/installer -O - -q | php -- --quiet --install-dir=/usr/local/bin/ --filename=composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
@@ -189,7 +200,7 @@
       python3-wheel \
       python3-zope.interface && \
     pip install -U ipaddress backports.ssl_match_hostname tornado && \
-    pip3 install -U backports.ssl_match_hostname tornado 
+    pip3 install -U backports.ssl_match_hostname tornado
 # installing tornado by pip/pip3 instead of debian package
 # if we install the debian package, the build fails in py2
 
@@ -211,6 +222,16 @@
       sloccount && \
     pip install flake8
 
+# Install BouncyCastle provider to fix Java builds issues with JDK 7
+# Builds accessing repote repositories fail as seen here: https://github.com/travis-ci/travis-ci/issues/8503
+RUN apt-get install -y --no-install-recommends \
+`# BouncyCastle JCE Provider dependencies` \
+      libbcprov-java && \
+    ln -s /usr/share/java/bcprov.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext/bcprov.jar && \
+    awk -F . -v OFS=. 'BEGIN{n=2}/^security\.provider/ {split($3, posAndEquals, "=");$3=n++"="posAndEquals[2];print;next} 1' /etc/java-7-openjdk/security/java.security > /tmp/java.security && \
+  echo "security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider" >> /tmp/java.security && \
+  mv /tmp/java.security /etc/java-7-openjdk/security/java.security
+
 # Clean up
 RUN rm -rf /var/cache/apt/* && \
     rm -rf /var/lib/apt/lists/* && \
diff --git a/build/docker/scripts/covscan.sh b/build/docker/scripts/covscan.sh
new file mode 100755
index 0000000..cb3f283
--- /dev/null
+++ b/build/docker/scripts/covscan.sh
@@ -0,0 +1,50 @@
+#
+# Coverity Scan Travis build script
+# To run this interactively, set the environment variables yourself,
+# and run this inside a docker container.
+#
+# Command-Line Arguments
+#
+# --skipdownload   to skip re-downloading the Coverity Scan build package (large)
+#
+# Environment Variables (required)
+#
+# COVERITY_SCAN_NOTIFICATION_EMAIL  - email address to notify
+# COVERITY_SCAN_TOKEN               - the Coverity Scan token (should be secure)
+#
+# Environment Variables (defaulted)
+#
+# COVERITY_SCAN_BUILD_COMMAND       - defaults to "build/docker/scripts/autotools.sh"
+# COVERITY_SCAN_DESCRIPTION         - defaults to TRAVIS_BRANCH or "master" if empty
+# COVERITY_SCAN_PROJECT             - defaults to "thrift"
+
+set -ex
+
+COVERITY_SCAN_BUILD_COMMAND=${COVERITY_SCAN_BUILD_COMMAND:-build/docker/scripts/autotools.sh}
+COVERITY_SCAN_DESCRIPTION=${COVERITY_SCAN_DESCRIPTION:-${TRAVIS_BRANCH:-master}}
+COVERITY_SCAN_PROJECT=${COVERITY_SCAN_PROJECT:-thrift}
+
+# download the coverity scan package
+
+pushd /tmp
+if [[ "$1" != "--skipdownload" ]]; then
+  rm -rf coverity_tool.tgz cov-analysis*
+  wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT" -O coverity_tool.tgz
+  tar xzf coverity_tool.tgz
+fi
+COVBIN=$(echo $(pwd)/cov-analysis*/bin)
+export PATH=$COVBIN:$PATH
+popd
+
+# build the project with coverity scan
+
+rm -rf cov-int/
+cov-build --dir cov-int $COVERITY_SCAN_BUILD_COMMAND
+tar cJf cov-int.tar.xz cov-int/
+curl --form token="$COVERITY_SCAN_TOKEN" \
+     --form email="$COVERITY_SCAN_NOTIFICATION_EMAIL" \
+     --form file=@cov-int.tar.xz \
+     --form version="$(git describe --tags)" \
+     --form description="$COVERITY_SCAN_DESCRIPTION" \
+     https://scan.coverity.com/builds?project="$COVERITY_SCAN_PROJECT"
+
diff --git a/build/docker/scripts/sca.sh b/build/docker/scripts/sca.sh
index 38803d4..16d5826 100755
--- a/build/docker/scripts/sca.sh
+++ b/build/docker/scripts/sca.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 set -ev
 
 #
@@ -39,16 +39,20 @@
 cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/c_glib/src lib/c_glib/test test/c_glib/src tutorial/c_glib
 
 # Python code style
-flake8 --ignore=E501 lib/py
-flake8 tutorial/py
+flake8 --ignore=W504,E501 lib/py
+flake8 --exclude=tutorial/py/build tutorial/py
 # THRIFT-4371 : generated files are excluded because they haven't been scrubbed yet
-flake8 --ignore=E501 --exclude="*/gen-py*/*" test/py
+flake8 --ignore=E501 --exclude="*/gen-py*/*",test/py/build test/py
 flake8 test/py.twisted
 flake8 test/py.tornado
 flake8 --ignore=E501 test/test.py
 flake8 --ignore=E501,E722 test/crossrunner
 flake8 test/features
 
+# PHP code style
+composer install --quiet
+./vendor/bin/phpcs
+
 # TODO etc
 echo FIXMEs: `grep -r FIXME * | wc -l`
 echo  HACKs: `grep -r HACK * | wc -l`
diff --git a/build/docker/ubuntu-artful/Dockerfile b/build/docker/ubuntu-artful/Dockerfile
index cba2902..abe84d1 100644
--- a/build/docker/ubuntu-artful/Dockerfile
+++ b/build/docker/ubuntu-artful/Dockerfile
@@ -14,18 +14,22 @@
 # Apache Thrift Docker build environment for Ubuntu Artful
 # Using all stock Ubuntu Artful packaging except for:
 # - cpp: stock boost 1.62 in artful has a nasty bug so we use stock boost 1.63
-# - d: does not come with Ubuntu so we're installing the latest
-# - d: deimos for libevent and openssl omitted - not compatible / build errors
-# - haxe: see THRIFT-4352, but test/haxe cores during testing
-#         and hxcpp 3.4.64 is not compatible with artful
+# - d: dmd does not come with Ubuntu
+# - dart: does not come with Ubuntu. Pinned to last 1.x release
+# - dotnet: does not come with Ubuntu
+# - haxe: version 3.4.2 that comes with Ubuntu cores in our CI build
+# - go: artful comes with 1.9, we want the latest (supported)
+# - nodejs: want v8, artful comes with v6
 #
 
 FROM buildpack-deps:artful-scm
 MAINTAINER Apache Thrift <dev@thrift.apache.org>
 ENV DEBIAN_FRONTEND noninteractive
 
-RUN apt-get update && \ 
-    apt-get dist-upgrade -y && \ 
+### Add apt repos
+
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
     apt-get install -y --no-install-recommends \
       apt \
       apt-transport-https \
@@ -39,15 +43,26 @@
 # RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \
 #     apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF
 
-# dotnet (core)
-RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
-    echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-artful-prod artful main" > /etc/apt/sources.list.d/dotnetdev.list
+# Dart
+RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
+    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
+      /etc/apt/sources.list.d/dart_stable.list
+ENV DART_VERSION 1.24.3-1
 
-# node.js (this step runs apt-get update internally) - if we ever want a later version
-RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
+# dotnet (netcore)
+RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
+    echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-artful-prod artful main" > \
+      /etc/apt/sources.list.d/dotnetdev.list
+
+# haxe (https://haxe.org/download/linux/)
+RUN add-apt-repository ppa:haxe/releases -y
+
+# node.js
+RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
+    echo "deb https://deb.nodesource.com/node_8.x artful main" | tee /etc/apt/sources.list.d/nodesource.list
 
 ### install general dependencies
-RUN apt-get install -y --no-install-recommends \
+RUN apt-get update && apt-get install -y --no-install-recommends \
 `# General dependencies` \
       bash-completion \
       bison \
@@ -78,49 +93,42 @@
 `# csharp (mono) dependencies` \
       mono-devel
 
-RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \
-    wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \
-    wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - && \
-    apt-get update && \
-    apt-get install -y --no-install-recommends \
-      `# D dependencies` \
-      dmd-bin \
-      libphobos2-dev \
-      dub \
-      dfmt \
-      dscanner \
-      libevent-dev \
-      libssl-dev \
-      xdg-utils
-# libevent deimos doesn't seem to work so not enabling it:
-# RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
-#     curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
-#     mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf libevent-master
-# openssl deimos doesn't work with openssl-1.0.2 so not enabling it:
-# RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
-#     mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf openssl-master
+ENV SBCL_VERSION 1.4.5
+RUN \
+`# Common Lisp (sbcl) dependencies` \
+    curl --version && \
+    curl -O -J -L https://kent.dl.sourceforge.net/project/sbcl/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
+    tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
+    cd sbcl-${SBCL_VERSION}-x86-64-linux && \
+    ./install.sh && \
+    sbcl --version && \
+    rm -rf sbcl*
 
-# dart cannot be downloaded by aptitude because of
-# https://github.com/dart-lang/sdk/issues/30512
-# RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
-#     curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \
-#     apt-get update && \
-#     apt-get install -y --no-install-recommends \
-#       `# Dart dependencies` \
-#       dart
-# so instead we do:
-RUN wget https://storage.googleapis.com/dart-archive/channels/stable/release/latest/linux_packages/dart_1.24.2-1_amd64.deb && \
-    dpkg -i dart_1.24.2-1_amd64.deb && \
-    rm dart_1.24.2-1_amd64.deb
+ENV D_VERSION     2.080.0
+ENV DMD_DEB       dmd_2.080.0-0_amd64.deb
+RUN \
+`# D dependencies` \
+    wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \
+    dpkg --install ${DMD_DEB} && \
+    rm -f ${DMD_DEB} && \
+    mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
+    curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
+    mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf libevent-master && \
+    curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
+    mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf openssl-master
+
+RUN apt-get install -y --no-install-recommends \
+      `# Dart dependencies` \
+      dart=$DART_VERSION
 ENV PATH /usr/lib/dart/bin:$PATH
 
 RUN apt-get install -y --no-install-recommends \
 `# dotnet core dependencies` \
-      dotnet-sdk-2.0.3
+      dotnet-sdk-2.1.4
 
 RUN apt-get install -y --no-install-recommends \
 `# Erlang dependencies` \
@@ -134,24 +142,28 @@
 `# GlibC dependencies` \
       libglib2.0-dev
 
-RUN apt-get install -y --no-install-recommends \
-`# golang (go) dependencies` \
-      golang-go \
-      golang-race-detector-runtime
+# golang
+ENV GOLANG_VERSION 1.10
+ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
+ENV GOLANG_DOWNLOAD_SHA256 b5a64335f1490277b585832d1f6c7f8c6c11206cba5cd3f771dcb87b98ad1a33
+RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
+      echo "$GOLANG_DOWNLOAD_SHA256  golang.tar.gz" | sha256sum -c - && \
+            tar -C /usr/local -xzf golang.tar.gz && \
+                  ln -s /usr/local/go/bin/go /usr/local/bin && \
+                        rm golang.tar.gz
 
 RUN apt-get install -y --no-install-recommends \
 `# Haskell dependencies` \
       ghc \
       cabal-install
 
-# see THRIFT-4352, test/haxe cores on artful
-# RUN apt-get install -y --no-install-recommends \
-# `# Haxe dependencies` \
-#       haxe \
-#       neko \
-#       neko-dev
-# RUN haxelib setup --always /usr/share/haxe/lib && \
-#     haxelib install --always hxcpp
+RUN apt-get install -y --no-install-recommends \
+`# Haxe dependencies` \
+      haxe \
+      neko \
+      neko-dev && \
+    haxelib setup --always /usr/share/haxe/lib && \
+    haxelib install --always hxcpp 2>&1 > /dev/null
 
 RUN apt-get install -y --no-install-recommends \
 `# Java dependencies` \
@@ -172,6 +184,11 @@
 `# Node.js dependencies` \
       nodejs
 
+# Test dependencies for running puppeteer
+RUN apt-get install -y --no-install-recommends \
+`# JS dependencies` \
+      libxss1
+
 RUN apt-get install -y --no-install-recommends \
 `# OCaml dependencies` \
       ocaml \
@@ -194,7 +211,7 @@
       php-dev \
       php-pear \
       re2c \
-      phpunit
+      composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
@@ -229,7 +246,6 @@
       ruby \
       ruby-dev \
       ruby-bundler
-RUN gem install bundler --no-ri --no-rdoc
 
 RUN apt-get install -y --no-install-recommends \
 `# Rust dependencies` \
diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile
new file mode 100644
index 0000000..43c99a9
--- /dev/null
+++ b/build/docker/ubuntu-bionic/Dockerfile
@@ -0,0 +1,279 @@
+# Licensed 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.
+
+#
+# Apache Thrift Docker build environment for Ubuntu Bionic
+# Using all stock Ubuntu Bionic packaging except for:
+# - cl: want latest
+# - d: dmd does not come with Ubuntu
+# - dart: does not come with Ubuntu. Pinned to last 1.x release
+# - dotnet: does not come with Ubuntu
+# - go: want latest
+# - nodejs: want v8, bionic comes with v6
+#
+
+FROM buildpack-deps:bionic-scm
+MAINTAINER Apache Thrift <dev@thrift.apache.org>
+ENV DEBIAN_FRONTEND noninteractive
+
+### Add apt repos
+
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
+    apt-get install -y --no-install-recommends \
+      apt \
+      apt-transport-https \
+      apt-utils \
+      curl \
+      dirmngr \
+      software-properties-common \
+      wget
+
+# csharp (mono) - if we ever want a later version
+# RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \
+#     apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF
+
+# Dart
+RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
+    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
+      /etc/apt/sources.list.d/dart_stable.list
+ENV DART_VERSION 1.24.3-1
+
+# dotnet (netcore)
+RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
+    wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \
+    chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \
+    chown root:root /etc/apt/sources.list.d/microsoft-prod.list
+
+# node.js
+RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
+    echo "deb https://deb.nodesource.com/node_8.x bionic main" | tee /etc/apt/sources.list.d/nodesource.list
+
+### install general dependencies
+RUN apt-get update && apt-get install -y --no-install-recommends \
+`# General dependencies` \
+      bash-completion \
+      bison \
+      build-essential \
+      clang \
+      cmake \
+      debhelper \
+      flex \
+      gdb \
+      llvm \
+      ninja-build \
+      pkg-config \
+      valgrind \
+      vim
+ENV PATH /usr/lib/llvm-6.0/bin:$PATH
+
+RUN apt-get install -y --no-install-recommends \
+`# C++ dependencies` \
+      libboost-all-dev \
+      libevent-dev \
+      libssl-dev \
+      qt5-default \
+      qtbase5-dev \
+      qtbase5-dev-tools
+
+RUN apt-get install -y --no-install-recommends \
+`# csharp (mono) dependencies` \
+      mono-devel
+
+ENV SBCL_VERSION 1.4.15
+RUN \
+`# Common Lisp (sbcl) dependencies` \
+    curl --version && \
+    curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \
+    tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
+    cd sbcl-${SBCL_VERSION}-x86-64-linux && \
+    ./install.sh && \
+    sbcl --version && \
+    cd .. && \
+    rm -rf sbcl*
+
+ENV D_VERSION     2.083.1
+ENV DMD_DEB       dmd_2.083.1-0_amd64.deb
+RUN \
+`# D dependencies` \
+    wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \
+    dpkg --install ${DMD_DEB} && \
+    rm -f ${DMD_DEB} && \
+    mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
+    git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \
+    mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf deimos-libevent-2.0 && \
+    git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \
+    mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf deimos-openssl-1.1.0h
+
+RUN apt-get install -y --no-install-recommends \
+      `# Dart dependencies` \
+      dart=$DART_VERSION
+ENV PATH /usr/lib/dart/bin:$PATH
+
+RUN apt-get install -y --no-install-recommends \
+`# dotnet core dependencies` \
+      dotnet-sdk-2.2
+
+RUN apt-get install -y --no-install-recommends \
+`# Erlang dependencies` \
+      erlang-base \
+      erlang-eunit \
+      erlang-dev \
+      erlang-tools \
+      rebar
+
+RUN apt-get install -y --no-install-recommends \
+`# GlibC dependencies` \
+      libglib2.0-dev
+
+# golang
+ENV GOLANG_VERSION 1.11.4
+ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
+ENV GOLANG_DOWNLOAD_SHA256 fb26c30e6a04ad937bbc657a1b5bba92f80096af1e8ee6da6430c045a8db3a5b
+RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
+      echo "$GOLANG_DOWNLOAD_SHA256  golang.tar.gz" | sha256sum -c - && \
+            tar -C /usr/local -xzf golang.tar.gz && \
+                  ln -s /usr/local/go/bin/go /usr/local/bin && \
+                        rm golang.tar.gz
+
+RUN apt-get install -y --no-install-recommends \
+`# Haskell dependencies` \
+      ghc \
+      cabal-install
+
+RUN apt-get install -y --no-install-recommends \
+`# Haxe dependencies` \
+      haxe \
+      neko \
+      neko-dev && \
+    haxelib setup --always /usr/share/haxe/lib && \
+    haxelib install --always hxcpp 2>&1 > /dev/null
+
+RUN apt-get install -y --no-install-recommends \
+`# Java dependencies` \
+      ant \
+      ant-optional \
+      openjdk-8-jdk \
+      maven && \
+    update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
+
+RUN apt-get install -y --no-install-recommends \
+`# Lua dependencies` \
+      lua5.2 \
+      lua5.2-dev
+# https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212
+# lua5.3 does not install alternatives!
+# need to update our luasocket code, lua doesn't have luaL_openlib any more
+
+RUN apt-get install -y --no-install-recommends \
+`# Node.js dependencies` \
+      nodejs
+
+# Test dependencies for running puppeteer
+RUN apt-get install -y --no-install-recommends \
+`# JS dependencies` \
+      libxss1
+
+RUN apt-get install -y --no-install-recommends \
+`# OCaml dependencies` \
+      ocaml \
+      opam && \
+    opam init --yes && \
+    opam install --yes oasis
+
+RUN apt-get install -y --no-install-recommends \
+`# Perl dependencies` \
+      libbit-vector-perl \
+      libclass-accessor-class-perl \
+      libcrypt-ssleay-perl \
+      libio-socket-ssl-perl \
+      libnet-ssleay-perl
+
+RUN apt-get install -y --no-install-recommends \
+`# Php dependencies` \
+      php \
+      php-cli \
+      php-dev \
+      php-pear \
+      re2c \
+      composer
+
+RUN apt-get install -y --no-install-recommends \
+`# Python dependencies` \
+      python-all \
+      python-all-dbg \
+      python-all-dev \
+      python-ipaddress \
+      python-pip \
+      python-setuptools \
+      python-six \
+      python-tornado \
+      python-twisted \
+      python-wheel \
+      python-zope.interface && \
+   pip install --upgrade backports.ssl_match_hostname
+
+RUN apt-get install -y --no-install-recommends \
+`# Python3 dependencies` \
+      python3-all \
+      python3-all-dbg \
+      python3-all-dev \
+      python3-pip \
+      python3-setuptools \
+      python3-six \
+      python3-tornado \
+      python3-twisted \
+      python3-wheel \
+      python3-zope.interface
+
+RUN apt-get install -y --no-install-recommends \
+`# Ruby dependencies` \
+      ruby \
+      ruby-dev \
+      ruby-bundler
+
+RUN apt-get install -y --no-install-recommends \
+`# Rust dependencies` \
+      cargo \
+      rustc
+
+# Swift on Linux for cross tests
+RUN cd / && \
+    wget --quiet https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \
+    tar xf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \
+    rm swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \
+    swift --version
+
+# cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer
+RUN apt-get install -y --no-install-recommends \
+`# Static Code Analysis dependencies` \
+      cppcheck \
+      sloccount && \
+    pip install flake8 && \
+    wget -q "https://launchpad.net/ubuntu/+source/cppcheck/1.83-2/+build/14874703/+files/cppcheck_1.83-2_amd64.deb" && \
+    dpkg -i cppcheck_1.83-2_amd64.deb && \
+    rm cppcheck_1.83-2_amd64.deb
+
+# Clean up
+RUN rm -rf /var/cache/apt/* && \
+    rm -rf /var/lib/apt/lists/* && \
+    rm -rf /tmp/* && \
+    rm -rf /var/tmp/*
+
+ENV THRIFT_ROOT /thrift
+RUN mkdir -p $THRIFT_ROOT/src
+COPY Dockerfile $THRIFT_ROOT/
+WORKDIR $THRIFT_ROOT/src
diff --git a/build/docker/ubuntu-trusty/Dockerfile.orig b/build/docker/ubuntu-trusty/Dockerfile.orig
deleted file mode 100644
index 857384b..0000000
--- a/build/docker/ubuntu-trusty/Dockerfile.orig
+++ /dev/null
@@ -1,231 +0,0 @@
-# Licensed 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.
-
-# Apache Thrift Docker build environment for Ubuntu
-#
-# Known missing client libraries:
-#  - dotnetcore
-
-FROM buildpack-deps:trusty-scm
-MAINTAINER Apache Thrift <dev@thrift.apache.org>
-
-ENV DEBIAN_FRONTEND noninteractive
-
-# Add apt sources
-# CMAKE
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends software-properties-common && \
-    add-apt-repository -y ppa:george-edison55/cmake-3.x
-
-# Erlang
-RUN echo 'deb http://packages.erlang-solutions.com/debian trusty contrib' > /etc/apt/sources.list.d/erlang_solutions.list && \
-    curl -sSL https://packages.erlang-solutions.com/debian/erlang_solutions.asc | apt-key add -
-
-# Dart
-RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
-    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \
-    sed -i /etc/apt/sources.list.d/dart_stable.list -e 's/https:/http:/g'
-
-# Consider using mirror nearby when building locally
-# TODO: Provide option via --build-arg=...
-# RUN sed -i /etc/apt/sources.list -e 's!http://archive.ubuntu.com/ubuntu/!http://your/mirror/!g'
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-`# General dependencies` \
-      bison \
-      build-essential \
-      clang \
-      cmake \
-      debhelper \
-      flex \
-      ninja-build \
-      pkg-config \
-`# Included in buildpack-deps` \
-`#      autoconf` \
-`#      automake` \
-`#      g++` \
-`#      git` \
-`#      libtool` \
-`#      make`
-
-RUN apt-get install -y --no-install-recommends \
-`# C++ dependencies` \
-`# libevent and OpenSSL are needed by D too` \
-      libboost-dev \
-      libboost-filesystem-dev \
-      libboost-program-options-dev \
-      libboost-system-dev \
-      libboost-test-dev \
-      libboost-thread-dev \
-      libevent-dev \
-      libssl-dev \
-      qt5-default \
-      qtbase5-dev \
-      qtbase5-dev-tools
-
-RUN apt-get install -y --no-install-recommends \
-`# Java dependencies` \
-      ant \
-      ant-optional \
-      openjdk-7-jdk \
-      maven
-
-RUN apt-get install -y --no-install-recommends \
-`# Python dependencies` \
-`# TODO:` \
-`# Install twisted and zope.interface via pip. we need twisted at ./configure time, otherwise` \
-`# py.twisted tests are skipped.` \
-      python-all \
-      python-all-dbg \
-      python-all-dev \
-      python-pip \
-      python-setuptools \
-      python-twisted \
-      python-zope.interface \
-      python3-all \
-      python3-all-dbg \
-      python3-all-dev \
-      python3-setuptools \
-      python3-pip
-
-RUN apt-get install -y --no-install-recommends \
-`# Ruby dependencies` \
-      ruby \
-      ruby-dev \
-      ruby-bundler \
-`# Perl dependencies` \
-      libbit-vector-perl \
-      libclass-accessor-class-perl \
-      libcrypt-ssleay-perl \
-      libio-socket-ssl-perl \
-      libnet-ssleay-perl
-
-RUN apt-get install -y --no-install-recommends \
-`# Php dependencies` \
-      php5 \
-      php5-dev \
-      php5-cli \
-      php-pear \
-      re2c \
-      phpunit \
-`# GlibC dependencies` \
-      libglib2.0-dev
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-`# Erlang dependencies` \
-      erlang-base \
-      erlang-eunit \
-      erlang-dev \
-      erlang-tools \
-      rebar
-
-RUN apt-get install -y --no-install-recommends \
-`# Haskell dependencies` \
-      ghc \
-      cabal-install \
-`# Haxe dependencies` \
-      neko \
-      neko-dev \
-      libneko0
-
-# Newer release of nodejs
-RUN curl -sL https://deb.nodesource.com/setup_4.x | bash
-RUN apt-get install -y --no-install-recommends \
-`# Node.js dependencies` \
-      nodejs
-
-# Add mono package repository url to get latest version of mono
-RUN echo "deb http://download.mono-project.com/repo/debian trusty main" | tee /etc/apt/sources.list.d/mono.list
-RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF
-RUN apt-get update && apt-get install -y --no-install-recommends \
-`# CSharp dependencies` \
-      mono-devel
-
-RUN apt-get install -y --no-install-recommends \
-`# D dependencies` \
-      xdg-utils \
-`# Dart dependencies` \
-      dart \
-`# Lua dependencies` \
-      lua5.2 \
-      lua5.2-dev \
-`# MinGW dependencies` \
-      mingw32 \
-      mingw32-binutils \
-      mingw32-runtime \
-      nsis \
-`# Clean up` \
-    && rm -rf /var/cache/apt/* && \
-    rm -rf /var/lib/apt/lists/* && \
-    rm -rf /tmp/* && \
-    rm -rf /var/tmp/*
-
-# Ruby
-RUN gem install bundler --no-ri --no-rdoc
-
-# Python optional dependencies
-RUN pip2 install -U ipaddress backports.ssl_match_hostname tornado
-RUN pip3 install -U backports.ssl_match_hostname tornado
-
-# Go
-RUN curl -sSL https://storage.googleapis.com/golang/go1.4.3.linux-amd64.tar.gz | tar -C /usr/local/ -xz
-ENV PATH /usr/local/go/bin:$PATH
-
-# Haxe
-RUN mkdir -p /usr/lib/haxe && \
-    wget -O - https://github.com/HaxeFoundation/haxe/releases/download/3.2.1/haxe-3.2.1-linux64.tar.gz | \
-    tar -C /usr/lib/haxe --strip-components=1 -xz && \
-    ln -s /usr/lib/haxe/haxe /usr/bin/haxe && \
-    ln -s /usr/lib/haxe/haxelib /usr/bin/haxelib && \
-    mkdir -p /usr/lib/haxe/lib  && \
-    chmod -R 777 /usr/lib/haxe/lib && \
-    haxelib setup --always /usr/lib/haxe/lib && \
-    haxelib install --always hxcpp 3.4.64
-
-# Node.js
-# temporarily removed since this breaks the build (and is not needed to test C# code)
-# RUN curl -sSL https://www.npmjs.com/install.sh | sh
-
-# D
-RUN curl -sSL http://downloads.dlang.org/releases/2.x/2.070.0/dmd_2.070.0-0_amd64.deb -o /tmp/dmd_2.070.0-0_amd64.deb && \
-    dpkg -i /tmp/dmd_2.070.0-0_amd64.deb && \
-    rm /tmp/dmd_2.070.0-0_amd64.deb && \
-    curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
-    curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
-    mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
-    mv libevent-master/deimos/* openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-    mv libevent-master/C/* openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
-    rm -rf libevent-master openssl-master && \
-    echo 'gcc -Wl,--no-as-needed $*' > /usr/local/bin/gcc-dmd && \
-    chmod 755 /usr/local/bin/gcc-dmd && \
-    echo 'CC=/usr/local/bin/gcc-dmd' >> /etc/dmd.conf
-
-# Dart
-ENV PATH /usr/lib/dart/bin:$PATH
-
-# OCaml
-RUN echo 'deb http://ppa.launchpad.net/avsm/ppa/ubuntu trusty main' > /etc/apt/sources.list.d/avsm-official-ocaml.list && \
-    gpg --keyserver keyserver.ubuntu.com --recv 61707B09 && \
-    gpg --export --armor 61707B09 | apt-key add - && \
-    apt-get update && \
-    apt-get install -y ocaml opam && \
-    opam init && \
-    opam install oasis
-
-# Rust
-RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.17.0
-ENV PATH /root/.cargo/bin:$PATH
-
-ENV THRIFT_ROOT /thrift
-RUN mkdir -p $THRIFT_ROOT/src
-COPY Dockerfile $THRIFT_ROOT/
-WORKDIR $THRIFT_ROOT/src
diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile
index c640bd9..3372b4d 100644
--- a/build/docker/ubuntu-xenial/Dockerfile
+++ b/build/docker/ubuntu-xenial/Dockerfile
@@ -13,46 +13,53 @@
 #
 # Apache Thrift Docker build environment for Ubuntu Xenial
 # Using all stock Ubuntu Xenial packaging except for:
-# - d: does not come with Ubuntu so we're installing 2.073.2 for coverage
+# - d: does not come with Ubuntu so we're installing 2.075.1 for coverage
 # - dart: does not come with Ubuntu so we're installing 1.22.1 for coverage
+# - dotnet: does not come with Ubuntu
+# - go: Xenial comes with 1.6, but we need 1.7 or later
+# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x
+# - ocaml: causes stack overflow error, just started March 2018 not sure why
 #
 
-#
-# Known missing or disabled libraries:
-# - d: deimos for libevent and openssl omitted - not compatible / build errors
-
 FROM buildpack-deps:xenial-scm
 MAINTAINER Apache Thrift <dev@thrift.apache.org>
 ENV DEBIAN_FRONTEND noninteractive
 
 ### Add apt repos
 
-RUN apt-get update && apt-get dist-upgrade -y && apt-get install -y --no-install-recommends apt apt-transport-https curl wget apt-utils
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
+    apt-get install -y --no-install-recommends \
+      apt \
+      apt-transport-https \
+      apt-utils \
+      curl \
+      software-properties-common \
+      wget
 
 # csharp (mono)
 # RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \
 #     apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF
 
 # D
-RUN wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \
+RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \
+    wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \
     wget -qO - https://dlang.org/d-keyring.gpg | apt-key add -
-ENV D_VERSION 2.073.2-0
 
 # Dart
 RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
-    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \
-    sed -i /etc/apt/sources.list.d/dart_stable.list -e 's/https:/http:/g'
-# since ubuntu-artful can't run dart, we'll run 1.240 on xenial for now
-ENV DART_VERSION 1.24.2-1
+    curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
+      /etc/apt/sources.list.d/dart_stable.list
+ENV DART_VERSION 1.22.1-1
 
 # dotnet (core)
 RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
-    echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list
+    echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > \
+      /etc/apt/sources.list.d/dotnetdev.list
 
-# node.js (this step runs apt-get update internally)
-# note: node 8.5 introduced some issues with directory handling / jsdoc / something... using 7.x for now
-# RUN curl -sL https://deb.nodesource.com/setup_7.x | bash
-
+# node.js
+RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
+    echo "deb https://deb.nodesource.com/node_6.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list
 
 ### install general dependencies
 RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -92,27 +99,26 @@
 `# csharp (mono) dependencies` \
       mono-devel
 
+ENV D_VERSION 2.075.1-0
 RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
 `# D dependencies` \
       dmd-bin=$D_VERSION \
       libphobos2-dev=$D_VERSION \
-      dub \
+      dub=1.6.0-0 \
       dfmt \
       dscanner \
       libevent-dev \
       libssl-dev \
       xdg-utils
-# libevent deimos doesn't seem to work so not enabling it:
-# RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
-#     curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
-#     mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf libevent-master
-# openssl deimos doesn't work with openssl-1.0.2 so not enabling it:
-# RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \
-#     mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
-#     mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \
-#     rm -rf openssl-master
+RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
+    curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \
+    mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf libevent-master
+RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/v1.1.6+1.0.1g.tar.gz | tar xz && \
+    mv openssl-1.1.6-1.0.1g/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
+    mv openssl-1.1.6-1.0.1g/C/* /usr/include/dmd/druntime/import/C/ && \
+    rm -rf openssl-1.1.6-1.0.1g
 
 RUN apt-get install -y --no-install-recommends \
 `# Dart dependencies` \
@@ -121,7 +127,7 @@
 
 RUN apt-get install -y --no-install-recommends \
 `# dotnet core dependencies` \
-      dotnet-sdk-2.0.3
+      dotnet-sdk-2.1.4
 
 RUN apt-get install -y --no-install-recommends \
 `# Erlang dependencies` \
@@ -135,24 +141,35 @@
 `# GlibC dependencies` \
       libglib2.0-dev
 
-RUN apt-get install -y --no-install-recommends \
-`# golang (go) dependencies` \
-      golang-go \
-      golang-race-detector-runtime
+# golang
+ENV GOLANG_VERSION 1.7.6
+ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
+ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea
+RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
+      echo "$GOLANG_DOWNLOAD_SHA256  golang.tar.gz" | sha256sum -c - && \
+      tar -C /usr/local -xzf golang.tar.gz && \
+      ln -s /usr/local/go/bin/go /usr/local/bin && \
+      rm golang.tar.gz
 
+# due to a bug in cabal in xenial (cabal-install package) we pull in another:
 RUN apt-get install -y --no-install-recommends \
 `# Haskell dependencies` \
-      ghc \
-      cabal-install
+      ghc && \
+    cd /tmp && \
+    wget -q https://www.haskell.org/cabal/release/cabal-install-1.24.0.2/cabal-install-1.24.0.2-x86_64-unknown-linux.tar.gz && \
+    tar xzf cabal-install-1.24.0.2-x86_64-unknown-linux.tar.gz && \
+    find dist-newstyle/ -type f -name cabal -exec mv {} /usr/bin \; && \
+    rm -rf /tmp/cabal* && \
+    cabal --version
 
 RUN apt-get install -y --no-install-recommends \
 `# Haxe dependencies` \
       haxe \
       neko \
       neko-dev \
-      libneko0
-RUN haxelib setup --always /usr/share/haxe/lib && \
-    haxelib install --always hxcpp 3.4.64
+      libneko0 && \
+    haxelib setup --always /usr/share/haxe/lib && \
+    haxelib install --always hxcpp 3.4.64 2>&1 > /dev/null
 # note: hxcpp 3.4.185 (latest) no longer ships static libraries, and caused a build failure
 
 RUN apt-get install -y --no-install-recommends \
@@ -171,16 +188,22 @@
 
 RUN apt-get install -y --no-install-recommends \
 `# Node.js dependencies` \
-      nodejs \
-      npm && \
-    ln -s /usr/bin/nodejs /usr/bin/node
+      nodejs
 
+# Test dependencies for running puppeteer
 RUN apt-get install -y --no-install-recommends \
-`# OCaml dependencies` \
-      ocaml \
-      opam && \
-    opam init --yes && \
-    opam install --yes oasis
+`# JS dependencies` \
+      libxss1 \
+      libatk-bridge2.0-0 \
+      libgtk-3-0
+
+# THRIFT-4517: causes stack overflows; version too old; skip ocaml in xenial
+# RUN apt-get install -y --no-install-recommends \
+# `# OCaml dependencies` \
+#       ocaml \
+#       opam && \
+#     opam init --yes && \
+#     opam install --yes oasis
 
 RUN apt-get install -y --no-install-recommends \
 `# Perl dependencies` \
@@ -197,7 +220,7 @@
       php7.0-dev \
       php-pear \
       re2c \
-      phpunit
+      composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
@@ -229,7 +252,6 @@
       ruby \
       ruby-dev \
       ruby-bundler
-RUN gem install bundler --no-ri --no-rdoc
 
 RUN apt-get install -y --no-install-recommends \
 `# Rust dependencies` \
diff --git a/build/fixchanges.sh b/build/fixchanges.sh
new file mode 100755
index 0000000..6c57b54
--- /dev/null
+++ b/build/fixchanges.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+#
+# fixchanges will take a file as input and look for text matching
+# the pattern [THRIFT-nnnn] (the number of digits is not important)
+# which is not a markdown link, and change it to be a markdown link.
+# The tool writes to stdout so you can redirect it to a temporary
+# file and then compare against the original file before replacing
+# it.
+#
+# This tool was developed after the 0.12.0 release to assist with
+# generation of CHANGES.md content.
+#
+
+while IFS='' read -r line || [[ -n "$line" ]]; do
+    if [[ "$line" =~ ^(.*)\[(THRIFT-[[:digit:]]+)\][^\(](.*)$ ]]; then
+        echo "${BASH_REMATCH[1]}[${BASH_REMATCH[2]}](https://issues.apache.org/jira/browse/${BASH_REMATCH[2]}) ${BASH_REMATCH[3]}"
+    else
+        echo "$line"
+    fi
+done < "$1"
diff --git a/build/travis/installCXXDependencies.sh b/build/travis/installCXXDependencies.sh
deleted file mode 100755
index ac3edf3..0000000
--- a/build/travis/installCXXDependencies.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-
-# 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.
-
-
-# Mainly aiming Travis CI's Ubuntu machines for now
-# see what we need: http://thrift.apache.org/docs/install/ubuntu
-
-# General dependencies
-sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu/ trusty main restricted" -y
-sudo apt-get update -qq
-
-sudo apt-get install -qq libpango-1.0-0 libqt4-dev qtbase5-dev qtbase5-dev-tools qt5-default libboost-dev libboost-test-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libboost-thread-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev make cmake git debhelper bc nsis ninja-build
-dpkg -S /usr/include/boost/version.hpp
diff --git a/build/travis/installDependencies.sh b/build/travis/installDependencies.sh
deleted file mode 100755
index eab8c6b..0000000
--- a/build/travis/installDependencies.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-
-# 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.
-
-SCRIPTPATH=$( cd $(dirname $0) ; pwd -P )
-
-# Mainly aiming Travis CI's Ubuntu machines for now
-# see what we need: http://thrift.apache.org/docs/install/ubuntu
-
-# Java dependencies
-sudo apt-get install -qq ant openjdk-7-jdk
-sudo update-java-alternatives -s java-1.7.0-openjdk-amd64
-
-# Python dependencies
-sudo apt-get install -qq python-all python-all-dev python-all-dbg python-setuptools python-support python-twisted python-six python3-six
-
-# Ruby dependencies
-sudo apt-get install -qq ruby ruby-dev
-sudo gem install bundler rake
-
-# Perl dependencies
-sudo apt-get install -qq libbit-vector-perl libclass-accessor-class-perl libio-socket-ssl-perl libnet-ssleay-perl libcrypt-ssleay-perl
-
-# Php dependencies
-sudo apt-get install -qq php5 php5-dev php5-cli php-pear re2c
-
-# GlibC dependencies
-sudo apt-get install -qq libglib2.0-dev
-
-# Erlang dependencies
-sudo apt-get install -qq erlang-base erlang-eunit erlang-dev erlang-tools rebar
-
-# GO dependencies
-echo "golang-go golang-go/dashboard boolean false" | debconf-set-selections
-sudo apt-get -y install -qq golang golang-go
-
-# Haskell dependencies
-sudo add-apt-repository -y ppa:hvr/ghc
-sudo apt-get update
-sudo apt-get install cabal-install-1.20 ghc-$GHCVER
-
-# Lua dependencies
-sudo apt-get install -qq lua5.2 lua5.2-dev
-
-# Node.js dependencies
-sudo apt-get install -qq nodejs nodejs-dev npm
-sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
-
-# CSharp
-sudo apt-get install -qq mono-gmcs mono-devel libmono-system-web2.0-cil
-sudo apt-get install -qq mingw32 mingw32-binutils mingw32-runtime nsis
diff --git a/build/veralign.sh b/build/veralign.sh
new file mode 100755
index 0000000..61744b4
--- /dev/null
+++ b/build/veralign.sh
@@ -0,0 +1,313 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+#
+# The veralign script sets the appropriate versions in all of
+# the package configuration files for all of the supported
+# languages.  It is used to prepare a release or move master
+# forward to the next anticipated version.
+#
+# USAGE
+# -----------------------------------------------------------
+# usage: veralign.sh <oldVersion> <newVersion>
+#
+# EXAMPLE
+# -----------------------------------------------------------
+# $ ./veralign.sh 0.12.0 1.0.0
+# $ ./veralign.sh 1.0.0 1.1.0
+#
+# IMPORTANT USAGE NOTE
+# -----------------------------------------------------------
+# Define the environment variable DRYRUN to have the script
+# print out all matches to the oldVersion hilighted so that
+# you can verify it will change the right things.
+#
+
+declare -A FILES
+
+# These files require a manual touch:
+FILES[CHANGES.md]=manual
+FILES[debian/changelog]=manual
+FILES[doap.rdf]=manual
+
+# These files can be updated automatically:
+FILES[ApacheThrift.nuspec]=simpleReplace
+FILES[Thrift-swift3.podspec]=simpleReplace
+FILES[Thrift.podspec]=simpleReplace
+FILES[appveyor.yml]=simpleReplace
+FILES[bower.json]=jsonReplace
+FILES[build/cmake/DefineCMakeDefaults.cmake]=simpleReplace
+FILES[configure.ac]=configureReplace
+FILES[contrib/thrift.spec]=simpleReplace
+FILES[lib/cocoa/src/Thrift.h]=simpleReplace
+FILES[lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj]=simpleReplace
+FILES[lib/csharp/src/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/csharp/src/Thrift.csproj]=simpleReplace
+FILES[lib/csharp/test/Multiplex/Client/MultiplexClient.csproj]=simpleReplace
+FILES[lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/csharp/test/Multiplex/Server/MultiplexServer.csproj]=simpleReplace
+FILES[lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/d/src/thrift/base.d]=simpleReplace
+FILES[lib/dart/pubspec.yaml]=pubspecReplace
+FILES[lib/delphi/src/Thrift.pas]=simpleReplace
+FILES[lib/erl/src/thrift.app.src]=simpleReplace
+FILES[lib/haxe/haxelib.json]=simpleReplace
+FILES[lib/hs/thrift.cabal]=simpleReplace
+FILES[lib/java/gradle.properties]=simpleReplace
+FILES[lib/js/package.json]=jsonReplace
+FILES[lib/js/src/thrift.js]=simpleReplace
+FILES[lib/lua/Thrift.lua]=simpleReplace
+FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace
+FILES[lib/ocaml/_oasis]=simpleReplace
+FILES[lib/perl/lib/Thrift.pm]=simpleReplace
+FILES[lib/py/setup.py]=simpleReplace
+FILES[lib/rb/thrift.gemspec]=simpleReplace
+FILES[lib/rs/Cargo.toml]=simpleReplace
+FILES[lib/st/package.xml]=simpleReplace
+FILES[package.json]=jsonReplace
+FILES[sonar-project.properties]=simpleReplace
+FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[test/csharp/ThriftTest.csproj]=simpleReplace
+FILES[test/dart/test_client/pubspec.yaml]=pubspecReplace
+FILES[test/erl/src/thrift_test.app.src]=simpleReplace
+FILES[tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs]=simpleReplace
+FILES[tutorial/dart/client/pubspec.yaml]=pubspecReplace
+FILES[tutorial/dart/console_client/pubspec.yaml]=pubspecReplace
+FILES[tutorial/dart/server/pubspec.yaml]=pubspecReplace
+FILES[tutorial/delphi/DelphiClient/DelphiClient.dproj]=simpleReplace
+FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace
+FILES[tutorial/hs/ThriftTutorial.cabal]=simpleReplace
+FILES[tutorial/ocaml/_oasis]=simpleReplace
+
+if [ ! -f "CHANGES" ]; then
+    >&2 echo "error: run veralign.sh while in the thrift root directory"
+    exit 1
+fi
+
+if [ $# -ne 2 ]; then
+    >&2 echo "usage: veralign.sh <oldVersion> <newVersion>"
+    exit 1
+fi
+
+jq --version 1>/dev/null 2>/dev/null
+if [ $? -ne 0 ]; then
+    >&2 echo "error: the 'jq' package is not installed"
+    exit 1
+fi
+
+#
+# validateVersion: check that a version matches the major.minor.patch
+#   format which is the lowest common denominator supported by all
+#   project systems.
+# \param $1 the version
+# \returns 0 if the version is compliant
+#
+function validateVersion
+{
+    local result
+    local valid
+    valid=$(echo "$1" | sed '/^[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+$/!{q22}')
+    result=$?
+    if [ $result -eq 22 ]; then
+        >&2 echo "error: version '$1' does not conform to the required major.minor.patch format"
+        return ${result}
+    fi
+}
+
+OLDVERSION=$1
+NEWVERSION=$2
+validateVersion "${OLDVERSION}" || exit $?
+validateVersion "${NEWVERSION}" || exit $?
+
+#
+# escapeVersion: escape the version for use as a sed search
+# \param $1 the version to escape
+# \output the escaped string
+# \returns 0
+# \example VERSEARCH=$(escapeVersion "[1.0.0]"); echo $VERSEARCH; => "\[1\.0\.0\]"
+#
+function escapeVersion
+{
+    echo "$(echo $1 | sed 's/\./\\./g' | sed 's/\[/\\\[/g' | sed 's/\]/\\\]/g')"
+}
+
+# Set up verbose hilighting if running interactive
+if [ "$(tput colors)" -ne 0 ]; then
+    reverse=$(tput rev)
+    red=$(tput setaf 1)
+    green=$(tput setaf 2)
+    yellow=$(tput setaf 3)
+    normal=$(tput sgr0)
+fi
+
+declare -A MANUAL
+
+#
+# manual: note that update of said file is manual
+# \param $1 filename to do replacements on
+# \returns 0
+#
+function manual
+{
+    MANUAL["$1"]=""
+    return 0
+}
+
+#
+# configureReplace: replace the AC_INIT field in configure.ac
+# \param $1 filename to do replacements on
+# \returns 0 on success
+#
+
+function configureReplace
+{
+    replace "$1" "[thrift], [${OLDVERSION}]" "[thrift], [${NEWVERSION}]"
+}
+
+#
+# jsonReplace: replace a specific version field in a JSON file
+#   must be a top level "version" field in the json structure
+# \param $1 filename to do replacements on
+# \returns 0 on success
+#
+
+function jsonReplace
+{
+    local result
+    local output
+    if [ ! -z "$DRYRUN" ]; then
+        output=$(jq -e ".version" "$1")
+    else
+        output=$(jq -e ".version = \"${NEWVERSION}\"" "$1" > tmp.$$.json && mv tmp.$$.json "$1")
+    fi
+    result=$?
+    if [ $? -ne 0 ]; then
+        printf "%-60s | %5d | ${red}ERROR${normal}: version tag not found" "$1" "$count"
+        echo
+        return 1
+    elif [ ! -z "$DRYRUN" ]; then
+        output=${output%\"}
+        output=${output#\"}
+        printf "%-60s | %5d | MATCHES:   version: \"${reverse}${green}${output}${normal}\"" "$1" 1
+        echo
+        return 0
+    fi
+    printf "%-60s | %5d | ${green}OK${normal}" "$1" 1
+    echo
+    return 0
+}
+
+#
+# pubspecReplace: replace a specific version field in a YAML file
+#   must be a top level "version" field in the yaml structure
+#   did not find a package that preserves comments so this is
+#   somewhat brain-dead, but it gets the job done
+# \param $1 filename to do replacements on
+# \returns 0 on success
+#
+
+function pubspecReplace
+{
+    replace "$1" "version: ${OLDVERSION}" "version: ${NEWVERSION}"
+}
+
+#
+# replace: replace occurrences of one string with another
+#     the file specified must contain the old string at least once
+#     in order to be successful.
+# \param $1 filename to do replacements on
+# \param $2 the "old" string to be replaced
+# \param $3 the "new" striing to replace it with
+# \returns 0 on success
+#
+function replace
+{
+    local result
+    local output
+    local oldString="$2"
+    local newString="$3"
+    local oldRegex=$(escapeVersion "${oldString}")
+    local count=$(grep -Ec "${oldRegex}" "$1")
+    local verbose
+    if [ $count -eq 0 ]; then
+        printf "%-60s | %5d | ${red}NOT FOUND${normal}: ${oldString}" "$1" 0
+        echo
+        return 1
+    elif [ ! -z "$DRYRUN" ]; then
+        printf "%-60s | %5d | MATCHES:" "$1" "$count"
+        echo
+        while read -r line; do
+            echo " > $(echo "$line" | sed "s/${oldRegex}/${reverse}${green}${oldString}${normal}/g")"
+        done < <(grep -E "${oldRegex}" "$1")
+        return 0
+    fi
+    output=$(sed -i "s/${oldRegex}/${newString}/g" "$1")
+    result=$?
+    if [ $result -ne 0 ]; then
+        printf "%-60s | %5d | ${red}ERROR${normal}: %s" "$1" "$count" "$output"
+        echo
+        return 1
+    fi
+    printf "%-60s | %5d | ${green}OK${normal}" "$1" "$count"
+    echo
+    return 0
+}
+
+#
+# simpleReplace: replace occurrences of ${OLDVERSION} with ${NEWVERSION}
+#     the file specified must contain OLDVERSION at least once
+#     in order to be successful.
+# \param $1 filename to do replacements on
+# \param $2 the "old" string to be replaced
+# \param $3 the "new" striing to replace it with
+# \returns 0 on success
+#
+function simpleReplace
+{
+    replace "$1" "${OLDVERSION}" "${NEWVERSION}"
+}
+
+echo ""
+echo "Apache Thrift Version Alignment Tool"
+echo "------------------------------------"
+echo ""
+echo "Previous Version: ${OLDVERSION}"
+echo "     New Version: ${NEWVERSION}"
+echo ""
+echo "-------------------------------------------------------------+-------+----------------------"
+echo "Filename                                                     | Count | Status               "
+echo "-------------------------------------------------------------+-------+----------------------"
+
+for file in $(echo "${!FILES[@]}" | sort); do
+    ${FILES[$file]} $file || exit $?
+done
+
+echo
+echo "Files that must be modified manually:"
+echo
+for manu in $(echo "${!MANUAL[@]}" | sort); do
+    echo " > ${yellow}${manu}${normal}"
+done
+
+exit 0
diff --git a/build/wincpp/build-thrift.bat b/build/wincpp/build-thrift.bat
index ba3e476..b867acf 100644
--- a/build/wincpp/build-thrift.bat
+++ b/build/wincpp/build-thrift.bat
@@ -134,7 +134,6 @@
     -DOPENSSL_USE_STATIC_LIBS=OFF ^
     -DZLIB_LIBRARY=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH%\lib\zlib%ZLIB_LIB_SUFFIX%.lib ^
     -DZLIB_ROOT=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH% ^
-    -DWITH_BOOSTTHREADS=ON ^
     -DWITH_SHARED_LIB=OFF ^
     -DWITH_STATIC_LIB=ON || EXIT /B
 
diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt
index 5da28aa..0df790e 100644
--- a/compiler/cpp/CMakeLists.txt
+++ b/compiler/cpp/CMakeLists.txt
@@ -62,6 +62,9 @@
     src/thrift/audit/t_audit.cpp
 )
 
+set(thrift_compiler_LANGS
+)
+
 # This macro adds an option THRIFT_COMPILER_${NAME}
 # that allows enabling or disabling certain languages
 macro(THRIFT_ADD_COMPILER name description initial)
@@ -70,6 +73,7 @@
     option(${enabler} ${description} ${initial})
     if(${enabler})
         list(APPEND thrift-compiler_SOURCES ${src})
+        list(APPEND thrift_compiler_LANGS ${name})
     endif()
 endmacro()
 
@@ -109,7 +113,7 @@
 # we also add the current binary directory for generated files
 include_directories(${CMAKE_CURRENT_BINARY_DIR} src)
 
-if(NOT ${WITH_PLUGIN})
+if(NOT DEFINED WITH_PLUGIN OR NOT ${WITH_PLUGIN})
     list(APPEND thrift-compiler_SOURCES ${compiler_core})
 endif()
 
diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am
index 482a89a..0b8ef2e 100644
--- a/compiler/cpp/Makefile.am
+++ b/compiler/cpp/Makefile.am
@@ -71,7 +71,7 @@
                  src/thrift/parse/parse.cc \
                  src/thrift/generate/t_generator.h \
                  src/thrift/generate/t_oop_generator.h \
-                 src/thrift/generate/t_html_generator.h
+                 src/thrift/generate/t_html_generator.h 
 
 thrift_SOURCES = src/thrift/main.h \
                  src/thrift/main.cc \
@@ -88,6 +88,7 @@
                   src/thrift/generate/t_haxe_generator.cc \
                   src/thrift/generate/t_csharp_generator.cc \
                   src/thrift/generate/t_netcore_generator.cc \
+                  src/thrift/generate/t_netcore_generator.h \
                   src/thrift/generate/t_py_generator.cc \
                   src/thrift/generate/t_rb_generator.cc \
                   src/thrift/generate/t_perl_generator.cc \
@@ -108,7 +109,8 @@
                   src/thrift/generate/t_gv_generator.cc \
                   src/thrift/generate/t_d_generator.cc \
                   src/thrift/generate/t_lua_generator.cc \
-                  src/thrift/generate/t_rs_generator.cc
+                  src/thrift/generate/t_rs_generator.cc \
+                  src/thrift/generate/t_cl_generator.cc
 
 thrift_CPPFLAGS = -I$(srcdir)/src
 thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror
@@ -153,7 +155,7 @@
 include_generate_HEADERS = src/thrift/generate/t_generator.h \
                            src/thrift/generate/t_generator_registry.h \
                            src/thrift/generate/t_oop_generator.h \
-                           src/thrift/generate/t_html_generator.h
+                           src/thrift/generate/t_html_generator.h 
 
 include_parsedir = $(include_thriftdir)/parse
 include_parse_HEADERS = src/thrift/parse/t_service.h \
diff --git a/compiler/cpp/README.md b/compiler/cpp/README.md
index 2fff0d8..32eac9f 100644
--- a/compiler/cpp/README.md
+++ b/compiler/cpp/README.md
@@ -1,19 +1,49 @@
-# Build compiler using CMake
+# Build Thrift IDL compiler using CMake
 
-## build on Unix-like System
+<!-- TOC -->
 
-### build using cmake
+- [Build Thrift IDL compiler using CMake](#build-thrift-idl-compiler-using-cmake)
+    - [Build on Unix-like System](#build-on-unix-like-system)
+        - [Prerequisites](#prerequisites)
+        - [Build using CMake](#build-using-cmake)
+            - [Build with Eclipse IDE](#build-with-eclipse-ide)
+            - [Build with XCode IDE in MacOS](#build-with-xcode-ide-in-macos)
+            - [Usage of other IDEs](#usage-of-other-ides)
+    - [Build on Windows](#build-on-windows)
+        - [Prerequisites](#prerequisites-1)
+        - [Build using Git Bash](#build-using-git-bash)
+        - [Using Visual Studio and Win flex-bison](#using-visual-studio-and-win-flex-bison)
+        - [Cross compile using mingw32 and generate a Windows Installer with CPack](#cross-compile-using-mingw32-and-generate-a-windows-installer-with-cpack)
+- [Other cases](#other-cases)
+    - [Building the Thrift IDL compiler in Windows without CMake](#building-the-thrift-idl-compiler-in-windows-without-cmake)
+- [Unit tests for compiler](#unit-tests-for-compiler)
+    - [Using boost test](#using-boost-test)
+    - [Using Catch C++ test library](#using-catch-c-test-library)
+- [Have a Happy free time and holidays](#have-a-happy-free-time-and-holidays)
 
-Use the following steps to build using cmake:
+<!-- /TOC -->
+
+## Build on Unix-like System
+
+### Prerequisites
+- Install CMake
+- Install flex and bison
+
+### Build using CMake
+
+- Go to **thrift\compiler\cpp**
+- Use the following steps to build using cmake:
 
 ```
-mkdir cmake-build
-cd cmake-build
+mkdir cmake-build && cd cmake-build
 cmake ..
 make
 ```
 
-### Create an eclipse project
+#### Build with Eclipse IDE
+
+- Go to **thrift\compiler\cpp**
+- Use the following steps to build using cmake:
 
 ```
 mkdir cmake-ec && cd cmake-ec
@@ -23,8 +53,65 @@
 
 Now open the folder cmake-ec using eclipse.
 
+#### Build with XCode IDE in MacOS
 
-## Cross compile using mingw32 and generate a Windows Installer with CPack
+- Install/update flex, bison and cmake with brew
+
+```
+brew install cmake
+brew install bison
+```
+
+- Go to **thrift\compiler\cpp**
+- Run commands in command line:
+
+```
+mkdir cmake-build && cd cmake-build
+cmake -G "Xcode" -DWITH_PLUGIN=OFF ..
+cmake --build .
+```
+
+#### Usage of other IDEs
+
+Please check list of supported IDE 
+
+```
+cmake --help
+```
+
+## Build on Windows
+
+### Prerequisites
+- Install CMake - https://cmake.org/download/
+- In case if you want to build without Git Bash - install winflexbison - https://sourceforge.net/projects/winflexbison/
+- In case if you want to build with Visual Studio - install Visual Studio 
+  - Better to use the latest stable Visual Studio Community Edition - https://www.visualstudio.com/vs/whatsnew/ (ensure that you installed workload "Desktop Development with C++" for VS2017) - Microsoft added some support for CMake and improving it in Visual Studio
+
+### Build using Git Bash
+
+Git Bash provides flex and bison
+
+- Go to **thrift\compiler\cpp**
+- Use the following steps to build using cmake:
+
+```
+mkdir cmake-vs && cd cmake-vs
+cmake -DWITH_SHARED_LIB=off ..
+cmake --build .
+```
+
+### Using Visual Studio and Win flex-bison
+
+- Generate a Visual Studio project for version of Visual Studio which you have (**cmake --help** can show list of supportable VS versions):
+- Run commands in command line:
+```
+mkdir cmake-vs
+cd cmake-vs
+cmake -G "Visual Studio 15 2017" -DWITH_PLUGIN=OFF ..
+```
+- Now open the folder cmake-vs using Visual Studio.
+
+### Cross compile using mingw32 and generate a Windows Installer with CPack
 
 ```
 mkdir cmake-mingw32 && cd cmake-mingw32
@@ -32,49 +119,23 @@
 cpack
 ```
 
-# Build on windows
+# Other cases
 
-### using Git Bash
+## Building the Thrift IDL compiler in Windows without CMake
 
-Git Bash provides flex and bison, so you just need to do this:
+If you don't want to use CMake you can use the already available Visual Studio 2010 solution.
 
-```
-mkdir cmake-vs && cd cmake-vs
-cmake -DWITH_SHARED_LIB=off ..
-```
+The Visual Studio project contains pre-build commands to generate the thriftl.cc, thrifty.cc and thrifty.hh files which are necessary to build the compiler. 
 
-### using Win flex-bison
+These depend on bison, flex and their dependencies to work properly.
 
-In order to build on windows with winflexbison a few additional steps are necessary:
+Download flex & bison as described above. 
 
-1. Download winflexbison from http://sourceforge.net/projects/winflexbison/
-2. Extract the winflex bison files to for e.g. C:\winflexbison
-3. Make the CMake variables point to the correct binaries.
-  * FLEX_EXECUTABLE = C:/winbuild/win_flex.exe
-  * BISON_EXECUTABLE = C:/winbuild/win_bison.exe
-4. Generate a Visual Studio project:
-```
-mkdir cmake-vs && cd cmake-vs
-cmake -G "Visual Studio 12" -DWITH_SHARED_LIB=off ..
-```
-5. Now open the folder build_vs using Visual Studio 2013.
-
-# Building the Thrift IDL compiler in Windows
-
-If you don't want to use CMake you can use the already available Visual Studio
-2010 solution.
-The Visual Studio project contains pre-build commands to generate the
-thriftl.cc, thrifty.cc and thrifty.hh files which are necessary to build
-the compiler. These depend on bison, flex and their dependencies to
-work properly.
-Download flex & bison as described above.
-Place these binaries somewhere in the path and
-rename win_flex.exe and win_bison.exe to flex.exe and bison.exe respectively.
+Place these binaries somewhere in the path and rename win_flex.exe and win_bison.exe to flex.exe and bison.exe respectively.
 
 If this doesn't work on a system, try these manual pre-build steps.
 
-Open compiler.sln and remove the Pre-build commands under the project's
- Properties -> Build Events -> Pre-Build Events.
+Open compiler.sln and remove the Pre-build commands under the project's: Properties -> Build Events -> Pre-Build Events.
 
 From a command prompt:
 ```
@@ -99,3 +160,16 @@
 location (e.g. thrift/compiler/cpp/src).
 
 Build the compiler in Visual Studio.
+
+# Unit tests for compiler
+
+## Using boost test
+- pls check **test** folder
+
+## Using Catch C++ test library
+
+Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netcore** implementation)
+
+- pls check **tests** folder
+
+# Have a Happy free time and holidays 
\ No newline at end of file
diff --git a/compiler/cpp/compiler.vcxproj b/compiler/cpp/compiler.vcxproj
index 4b03253..0628b54 100644
--- a/compiler/cpp/compiler.vcxproj
+++ b/compiler/cpp/compiler.vcxproj
@@ -51,7 +51,7 @@
     <ClInclude Include="src\thrift\version.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="src\thrift\audit\t_audit.cpp"/>
+    <ClCompile Include="src\thrift\audit\t_audit.cpp" />
     <ClCompile Include="src\thrift\common.cc" />
     <ClCompile Include="src\thrift\generate\t_as3_generator.cc" />
     <ClCompile Include="src\thrift\generate\t_cocoa_generator.cc" />
@@ -196,7 +196,6 @@
     </Link>
     <PreBuildEvent>
       <Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
-
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -210,6 +209,7 @@
       <PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
       <CompileAs>CompileAsCpp</CompileAs>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -219,7 +219,6 @@
     </Link>
     <PreBuildEvent>
       <Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
-
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -233,6 +232,7 @@
       <PreprocessorDefinitions>WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ForcedIncludeFiles>thrift\windows\config.h</ForcedIncludeFiles>
       <CompileAs>CompileAsCpp</CompileAs>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -242,10 +242,9 @@
     </Link>
     <PreBuildEvent>
       <Command>flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll &amp;&amp; bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy</Command>
-
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp
index 1386f3b..ef39d60 100644
--- a/compiler/cpp/src/thrift/audit/t_audit.cpp
+++ b/compiler/cpp/src/thrift/audit/t_audit.cpp
@@ -202,8 +202,8 @@
          }
       case t_const_value::CV_MAP:
          {
-            const std::map<t_const_value*, t_const_value*> newMap = newStructDefault->get_map();
-            const std::map<t_const_value*, t_const_value*> oldMap = oldStructDefault->get_map();
+            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> newMap = newStructDefault->get_map();
+            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> oldMap = oldStructDefault->get_map();
 
             bool defaultValuesCompare = (oldMap.size() == newMap.size());
 
diff --git a/compiler/cpp/src/thrift/generate/t_as3_generator.cc b/compiler/cpp/src/thrift/generate/t_as3_generator.cc
index fc92de9..41724fe 100644
--- a/compiler/cpp/src/thrift/generate/t_as3_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_as3_generator.cc
@@ -31,7 +31,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -83,13 +83,13 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false);
-  std::string render_const_value(ofstream& out,
+  std::string render_const_value(ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
@@ -100,19 +100,19 @@
 
   void generate_as3_struct(t_struct* tstruct, bool is_exception);
 
-  void generate_as3_struct_definition(std::ofstream& out,
+  void generate_as3_struct_definition(std::ostream& out,
                                       t_struct* tstruct,
                                       bool is_xception = false,
                                       bool in_class = false,
                                       bool is_result = false);
   // removed -- equality,compare_to
-  void generate_as3_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_struct_tostring(std::ofstream& out, t_struct* tstruct, bool bindable);
-  void generate_as3_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  void generate_as3_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_as3_validator(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_tostring(std::ostream& out, t_struct* tstruct, bool bindable);
+  void generate_as3_meta_data_map(std::ostream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ostream& out, t_type* type);
   std::string get_as3_type_string(t_type* type);
   void generate_reflection_setters(std::ostringstream& out,
                                    t_type* type,
@@ -122,15 +122,15 @@
                                    t_type* type,
                                    std::string field_name,
                                    std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_as3_bean_boilerplate(std::ofstream& out, t_struct* tstruct, bool bindable);
+  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct);
+  void generate_as3_bean_boilerplate(std::ostream& out, t_struct* tstruct, bool bindable);
 
   void generate_function_helpers(t_function* tfunction);
   std::string get_cap_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
+  void generate_isset_set(ostream& out, t_field* field);
   // removed std::string isset_field_id(t_field* field);
 
   void generate_service_interface(t_service* tservice);
@@ -143,38 +143,38 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_as3_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_as3_doc(std::ostream& out, t_doc* tdoc);
 
-  void generate_as3_doc(std::ofstream& out, t_function* tdoc);
+  void generate_as3_doc(std::ostream& out, t_function* tdoc);
 
   /**
    * Helper rendering functions
@@ -208,7 +208,7 @@
    */
 
   std::string package_name_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
   std::string package_dir_;
 
   bool bindable_;
@@ -353,8 +353,8 @@
 void t_as3_generator::generate_enum(t_enum* tenum) {
   // Make output file
   string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".as";
-  ofstream f_enum;
-  f_enum.open(f_enum_name.c_str());
+  ofstream_with_content_based_conditional_update f_enum;
+  f_enum.open(f_enum_name);
 
   // Comment and package it
   f_enum << autogen_comment() << as3_package() << endl;
@@ -416,8 +416,8 @@
   }
 
   string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.as";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
+  ofstream_with_content_based_conditional_update f_consts;
+  f_consts.open(f_consts_name);
 
   // Print header
   f_consts << autogen_comment() << as3_package();
@@ -443,7 +443,7 @@
   f_consts.close();
 }
 
-void t_as3_generator::print_const_value(std::ofstream& out,
+void t_as3_generator::print_const_value(std::ostream& out,
                                         string name,
                                         t_type* type,
                                         t_const_value* value,
@@ -471,8 +471,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
         << endl;
     if (!in_static) {
@@ -516,8 +516,8 @@
     }
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
       string val = render_const_value(out, name, vtype, v_iter->second);
@@ -567,7 +567,7 @@
   }
 }
 
-string t_as3_generator::render_const_value(ofstream& out,
+string t_as3_generator::render_const_value(ostream& out,
                                            string name,
                                            t_type* type,
                                            t_const_value* value) {
@@ -644,7 +644,7 @@
 void t_as3_generator::generate_as3_struct(t_struct* tstruct, bool is_exception) {
   // Make output file
   string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".as";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << as3_package();
@@ -678,7 +678,7 @@
  * @param in_class     If inside a class, needs to be static class
  * @param is_result    If this is a result it needs a different writer
  */
-void t_as3_generator::generate_as3_struct_definition(ofstream& out,
+void t_as3_generator::generate_as3_struct_definition(ostream& out,
                                                      t_struct* tstruct,
                                                      bool is_exception,
                                                      bool in_class,
@@ -782,7 +782,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_as3_struct_reader(ostream& out, t_struct* tstruct) {
   out << indent() << "public function read(iprot:TProtocol):void {" << endl;
   indent_up();
 
@@ -862,7 +862,7 @@
 
 // generates as3 method to perform various checks
 // (e.g. check that all required fields are set)
-void t_as3_generator::generate_as3_validator(ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_as3_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "public function validate():void {" << endl;
   indent_up();
 
@@ -912,7 +912,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_as3_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public function write(oprot:TProtocol):void {" << endl;
   indent_up();
 
@@ -971,7 +971,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_as3_struct_result_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public function write(oprot:TProtocol):void {" << endl;
   indent_up();
 
@@ -1044,7 +1044,7 @@
   indent_down();
 }
 
-void t_as3_generator::generate_generic_field_getters_setters(std::ofstream& out,
+void t_as3_generator::generate_generic_field_getters_setters(std::ostream& out,
                                                              t_struct* tstruct) {
 
   std::ostringstream getter_stream;
@@ -1100,7 +1100,7 @@
 }
 
 // Creates a generic isSet method that takes the field number as argument
-void t_as3_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -1134,7 +1134,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_bean_boilerplate(ofstream& out,
+void t_as3_generator::generate_as3_bean_boilerplate(ostream& out,
                                                     t_struct* tstruct,
                                                     bool bindable) {
   const vector<t_field*>& fields = tstruct->get_members();
@@ -1216,7 +1216,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_struct_tostring(ofstream& out,
+void t_as3_generator::generate_as3_struct_tostring(ostream& out,
                                                    t_struct* tstruct,
                                                    bool bindable) {
   // If it's bindable, it extends EventDispatcher so toString is an override.
@@ -1293,7 +1293,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_as3_generator::generate_as3_meta_data_map(ofstream& out, t_struct* tstruct) {
+void t_as3_generator::generate_as3_meta_data_map(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -1381,7 +1381,7 @@
   }
 }
 
-void t_as3_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+void t_as3_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) {
   out << endl;
   indent_up();
   indent_up();
@@ -1960,7 +1960,7 @@
  * @param tfield The field
  * @param prefix The variable name or container for this field
  */
-void t_as3_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_as3_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   if (type->is_void()) {
@@ -2025,7 +2025,7 @@
 /**
  * Generates an unserializer for a struct, invokes read()
  */
-void t_as3_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_as3_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
       << prefix << ".read(iprot);" << endl;
 }
@@ -2033,7 +2033,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_as3_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_as3_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   string obj;
@@ -2093,7 +2093,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_as3_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_as3_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
@@ -2111,7 +2111,7 @@
 /**
  * Deserializes a set element
  */
-void t_as3_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_as3_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -2125,7 +2125,7 @@
 /**
  * Deserializes a list element
  */
-void t_as3_generator::generate_deserialize_list_element(ofstream& out,
+void t_as3_generator::generate_deserialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string prefix) {
   string elem = tmp("_elem");
@@ -2144,7 +2144,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_as3_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_as3_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2213,7 +2213,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_as3_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_as3_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   out << indent() << prefix << ".write(oprot);" << endl;
 }
@@ -2224,7 +2224,7 @@
  * @param ttype  The type of container
  * @param prefix String prefix for fields
  */
-void t_as3_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_as3_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -2282,7 +2282,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_as3_generator::generate_serialize_map_element(ofstream& out,
+void t_as3_generator::generate_serialize_map_element(ostream& out,
                                                      t_map* tmap,
                                                      string iter,
                                                      string map) {
@@ -2295,7 +2295,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_as3_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_as3_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2303,7 +2303,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_as3_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_as3_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2390,7 +2390,7 @@
   if (init) {
     t_type* ttype = get_true_type(tfield->get_type());
     if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
+      std::ofstream dummy;
       result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -2539,7 +2539,7 @@
 /**
  * Emits a As3Doc comment if the provided object has a doc in Thrift
  */
-void t_as3_generator::generate_as3_doc(ofstream& out, t_doc* tdoc) {
+void t_as3_generator::generate_as3_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n");
   }
@@ -2548,7 +2548,7 @@
 /**
  * Emits a As3Doc comment if the provided function object has a doc in Thrift
  */
-void t_as3_generator::generate_as3_doc(ofstream& out, t_function* tfunction) {
+void t_as3_generator::generate_as3_doc(ostream& out, t_function* tfunction) {
   if (tfunction->has_doc()) {
     stringstream ss;
     ss << tfunction->get_doc();
@@ -2573,7 +2573,7 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_as3_generator::generate_isset_set(ofstream& out, t_field* field) {
+void t_as3_generator::generate_isset_set(ostream& out, t_field* field) {
   if (!type_can_be_null(field->get_type())) {
     indent(out) << "this.__isset_" << field->get_name() << " = true;" << endl;
   }
diff --git a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
index a7beca7..be3bad1 100644
--- a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc
@@ -33,7 +33,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -116,10 +116,10 @@
 
 private:
   /* file streams */
-  ofstream f_types_;
-  ofstream f_types_impl_;
-  ofstream f_header_;
-  ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_types_impl_;
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_service_;
 
   /* namespace variables */
   string nspace;
@@ -145,8 +145,8 @@
                        bool pointer = false,
                        bool constant = false,
                        bool reference = false);
-  void declare_local_variable(ofstream& out, t_type* ttype, string& base_name, bool for_hash_table);
-  void declore_local_variable_for_write(ofstream& out, t_type* ttype, string& base_name);
+  void declare_local_variable(ostream& out, t_type* ttype, string& base_name, bool for_hash_table);
+  void declore_local_variable_for_write(ostream& out, t_type* ttype, string& base_name);
 
   /* generation functions */
   void generate_const_initializer(string name,
@@ -159,51 +159,51 @@
   void generate_service_processor(t_service* tservice);
   void generate_service_server(t_service* tservice);
   void generate_object(t_struct* tstruct);
-  void generate_struct_writer(ofstream& out,
+  void generate_struct_writer(ostream& out,
                               t_struct* tstruct,
                               string this_name,
                               string this_get = "",
                               bool is_function = true);
-  void generate_struct_reader(ofstream& out,
+  void generate_struct_reader(ostream& out,
                               t_struct* tstruct,
                               string this_name,
                               string this_get = "",
                               bool is_function = true);
 
-  void generate_serialize_field(ofstream& out,
+  void generate_serialize_field(ostream& out,
                                 t_field* tfield,
                                 string prefix,
                                 string suffix,
                                 int error_ret);
-  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix, int error_ret);
-  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
-  void generate_serialize_map_element(ofstream& out,
+  void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret);
+  void generate_serialize_container(ostream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_serialize_map_element(ostream& out,
                                       t_map* tmap,
                                       string key,
                                       string value,
                                       int error_ret);
-  void generate_serialize_set_element(ofstream& out, t_set* tset, string element, int error_ret);
-  void generate_serialize_list_element(ofstream& out,
+  void generate_serialize_set_element(ostream& out, t_set* tset, string element, int error_ret);
+  void generate_serialize_list_element(ostream& out,
                                        t_list* tlist,
                                        string list,
                                        string index,
                                        int error_ret);
 
-  void generate_deserialize_field(ofstream& out,
+  void generate_deserialize_field(ostream& out,
                                   t_field* tfield,
                                   string prefix,
                                   string suffix,
                                   int error_ret,
                                   bool allocate = true);
-  void generate_deserialize_struct(ofstream& out,
+  void generate_deserialize_struct(ostream& out,
                                    t_struct* tstruct,
                                    string prefix,
                                    int error_ret,
                                    bool allocate = true);
-  void generate_deserialize_container(ofstream& out, t_type* ttype, string prefix, int error_ret);
-  void generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix, int error_ret);
-  void generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix, int error_ret);
-  void generate_deserialize_list_element(ofstream& out,
+  void generate_deserialize_container(ostream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, int error_ret);
+  void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, int error_ret);
+  void generate_deserialize_list_element(ostream& out,
                                          t_list* tlist,
                                          string prefix,
                                          string index,
@@ -250,11 +250,21 @@
 
   /* include other thrift includes */
   const vector<t_program*>& includes = program_->get_includes();
-  for (size_t i = 0; i < includes.size(); ++i) {
-    f_types_ << "/* other thrift includes */" << endl << "#include \"" << this->nspace_lc
-             << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl;
+  if (!includes.empty()) {
+    f_types_ << "/* other thrift includes */" << endl;
+
+    for (vector<t_program*>::const_iterator iter = includes.begin();
+         iter != includes.end();
+         ++iter) {
+      const std::string& include_nspace = (*iter)->get_namespace("c_glib");
+      std::string include_nspace_prefix =
+        include_nspace.empty() ? "" : initial_caps_to_underscores(include_nspace) + "_";
+
+      f_types_ << "#include \"" << include_nspace_prefix
+               << initial_caps_to_underscores((*iter)->get_name()) << "_types.h\"" << endl;
+    }
+    f_types_ << endl;
   }
-  f_types_ << endl;
 
   /* include custom headers */
   const vector<string>& c_includes = program_->get_c_includes();
@@ -579,7 +589,7 @@
       // TODO: discuss whether or not to implement TSet, THashSet or GHashSet
       cname = "GHashTable";
     } else if (ttype->is_list()) {
-      t_type* etype = ((t_list*)ttype)->get_elem_type();
+      t_type* etype = get_true_type(((t_list*)ttype)->get_elem_type());
       if (etype->is_void()) {
         throw std::runtime_error("compiler error: list element type cannot be void");
       }
@@ -602,7 +612,8 @@
   }
 
   // check for a namespace
-  string pname = this->nspace + ttype->get_name();
+  t_program* tprogram = ttype->get_program();
+  string pname = (tprogram ? tprogram->get_namespace("c_glib") : "") + ttype->get_name();
 
   if (is_complex_type(ttype)) {
     pname += " *";
@@ -997,8 +1008,8 @@
   if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     ostringstream initializers;
 
     // initialize any constants that may be referenced by this initializer
@@ -1171,8 +1182,8 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     ostringstream initializers;
     ostringstream appenders;
 
@@ -1831,8 +1842,10 @@
   string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
   string service_name_uc = to_upper_case(service_name_lc);
 
-  string class_name = this->nspace + service_name_ + "Handler";
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string service_handler_name = service_name_ + "Handler";
+
+  string class_name = this->nspace + service_handler_name;
+  string class_name_lc = this->nspace_lc + initial_caps_to_underscores(service_handler_name);
   string class_name_uc = to_upper_case(class_name_lc);
 
   string parent_class_name;
@@ -2051,8 +2064,10 @@
   string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
   string service_name_uc = to_upper_case(service_name_lc);
 
-  string class_name = this->nspace + service_name_ + "Processor";
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string service_processor_name = service_name_ + "Processor";
+
+  string class_name = this->nspace + service_processor_name;
+  string class_name_lc = this->nspace_lc + initial_caps_to_underscores(service_processor_name);
   string class_name_uc = to_upper_case(class_name_lc);
 
   string parent_class_name;
@@ -2784,7 +2799,7 @@
   string name_uc = to_upper_case(name_u);
 
   string class_name = this->nspace + name;
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_lc = this->nspace_lc + initial_caps_to_underscores(name);
   string class_name_uc = to_upper_case(class_name_lc);
 
   string function_name;
@@ -3124,7 +3139,8 @@
                         << "THRIFT_UNUSED_VAR (object);" << endl;
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = get_true_type((*m_iter)->get_type());
+    t_type* member_type = (*m_iter)->get_type();
+    t_type* t = get_true_type(member_type);
     if (t->is_base_type()) {
       string dval = " = ";
       if (t->is_enum()) {
@@ -3139,10 +3155,14 @@
       indent(f_types_impl_) << "object->" << (*m_iter)->get_name() << dval << ";" << endl;
     } else if (t->is_struct()) {
       string name = (*m_iter)->get_name();
-      string type_name_uc
-          = to_upper_case(initial_caps_to_underscores((*m_iter)->get_type()->get_name()));
-      indent(f_types_impl_) << "object->" << name << " = g_object_new (" << this->nspace_uc
-                            << "TYPE_" << type_name_uc << ", NULL);" << endl;
+      t_program* type_program = member_type->get_program();
+      string type_nspace = type_program ? type_program->get_namespace("c_glib") : "";
+      string type_nspace_prefix =
+        type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_";
+      string type_name_uc = to_upper_case(initial_caps_to_underscores(member_type->get_name()));
+      indent(f_types_impl_) << "object->" << name << " = g_object_new ("
+                            << to_upper_case(type_nspace_prefix) << "TYPE_" << type_name_uc
+                            << ", NULL);" << endl;
     } else if (t->is_xception()) {
       string name = (*m_iter)->get_name();
       indent(f_types_impl_) << "object->" << name << " = NULL;" << endl;
@@ -3424,7 +3444,12 @@
                       << "G_PARAM_READWRITE));" << endl;
         indent_down();
       } else if (member_type->is_struct() || member_type->is_xception()) {
-        string param_type = this->nspace_uc + "TYPE_"
+        t_program* type_program = member_type->get_program();
+        string type_nspace = type_program ? type_program->get_namespace("c_glib") : "";
+        string type_nspace_prefix =
+          type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_";
+
+        string param_type = to_upper_case(type_nspace_prefix) + "TYPE_"
                             + to_upper_case(initial_caps_to_underscores(member_type->get_name()));
 
         args_indent += string(20, ' ');
@@ -3480,7 +3505,7 @@
 /**
  * Generates functions to write Thrift structures to a stream.
  */
-void t_c_glib_generator::generate_struct_writer(ofstream& out,
+void t_c_glib_generator::generate_struct_writer(ostream& out,
                                                 t_struct* tstruct,
                                                 string this_name,
                                                 string this_get,
@@ -3553,7 +3578,7 @@
 /**
  * Generates code to read Thrift structures from a stream.
  */
-void t_c_glib_generator::generate_struct_reader(ofstream& out,
+void t_c_glib_generator::generate_struct_reader(ostream& out,
                                                 t_struct* tstruct,
                                                 string this_name,
                                                 string this_get,
@@ -3690,7 +3715,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_c_glib_generator::generate_serialize_field(ofstream& out,
+void t_c_glib_generator::generate_serialize_field(ostream& out,
                                                   t_field* tfield,
                                                   string prefix,
                                                   string suffix,
@@ -3756,7 +3781,7 @@
   }
 }
 
-void t_c_glib_generator::generate_serialize_struct(ofstream& out,
+void t_c_glib_generator::generate_serialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix,
                                                    int error_ret) {
@@ -3766,7 +3791,7 @@
       << indent() << "xfer += ret;" << endl << endl;
 }
 
-void t_c_glib_generator::generate_serialize_container(ofstream& out,
+void t_c_glib_generator::generate_serialize_container(ostream& out,
                                                       t_type* ttype,
                                                       string prefix,
                                                       int error_ret) {
@@ -3923,7 +3948,7 @@
   scope_down(out);
 }
 
-void t_c_glib_generator::generate_serialize_map_element(ofstream& out,
+void t_c_glib_generator::generate_serialize_map_element(ostream& out,
                                                         t_map* tmap,
                                                         string key,
                                                         string value,
@@ -3935,7 +3960,7 @@
   generate_serialize_field(out, &vfield, "", "", error_ret);
 }
 
-void t_c_glib_generator::generate_serialize_set_element(ofstream& out,
+void t_c_glib_generator::generate_serialize_set_element(ostream& out,
                                                         t_set* tset,
                                                         string element,
                                                         int error_ret) {
@@ -3943,7 +3968,7 @@
   generate_serialize_field(out, &efield, "", "", error_ret);
 }
 
-void t_c_glib_generator::generate_serialize_list_element(ofstream& out,
+void t_c_glib_generator::generate_serialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string list,
                                                          string index,
@@ -3975,7 +4000,7 @@
 }
 
 /* deserializes a field of any type. */
-void t_c_glib_generator::generate_deserialize_field(ofstream& out,
+void t_c_glib_generator::generate_deserialize_field(ostream& out,
                                                     t_field* tfield,
                                                     string prefix,
                                                     string suffix,
@@ -4068,7 +4093,7 @@
   }
 }
 
-void t_c_glib_generator::generate_deserialize_struct(ofstream& out,
+void t_c_glib_generator::generate_deserialize_struct(ostream& out,
                                                      t_struct* tstruct,
                                                      string prefix,
                                                      int error_ret,
@@ -4101,7 +4126,7 @@
   out << indent() << "}" << endl << indent() << "xfer += ret;" << endl;
 }
 
-void t_c_glib_generator::generate_deserialize_container(ofstream& out,
+void t_c_glib_generator::generate_deserialize_container(ostream& out,
                                                         t_type* ttype,
                                                         string prefix,
                                                         int error_ret) {
@@ -4202,7 +4227,7 @@
   scope_down(out);
 }
 
-void t_c_glib_generator::declare_local_variable(ofstream& out, t_type* ttype, string& name, bool for_hash_table) {
+void t_c_glib_generator::declare_local_variable(ostream& out, t_type* ttype, string& name, bool for_hash_table) {
   string tname = type_name(ttype);
 
   /* If the given type is a typedef, find its underlying type so we
@@ -4226,7 +4251,7 @@
   }
 }
 
-void t_c_glib_generator::declore_local_variable_for_write(ofstream& out,
+void t_c_glib_generator::declore_local_variable_for_write(ostream& out,
                                                           t_type* ttype,
                                                           string& name) {
   string tname = type_name(ttype);
@@ -4236,7 +4261,7 @@
   out << indent() << tname << ptr << name << init_val << ";" << endl;
 }
 
-void t_c_glib_generator::generate_deserialize_map_element(ofstream& out,
+void t_c_glib_generator::generate_deserialize_map_element(ostream& out,
                                                           t_map* tmap,
                                                           string prefix,
                                                           int error_ret) {
@@ -4270,7 +4295,7 @@
   indent_down();
 }
 
-void t_c_glib_generator::generate_deserialize_set_element(ofstream& out,
+void t_c_glib_generator::generate_deserialize_set_element(ostream& out,
                                                           t_set* tset,
                                                           string prefix,
                                                           int error_ret) {
@@ -4290,7 +4315,7 @@
   indent_down();
 }
 
-void t_c_glib_generator::generate_deserialize_list_element(ofstream& out,
+void t_c_glib_generator::generate_deserialize_list_element(ostream& out,
                                                            t_list* tlist,
                                                            string prefix,
                                                            string index,
diff --git a/compiler/cpp/src/thrift/generate/t_cl_generator.cc b/compiler/cpp/src/thrift/generate/t_cl_generator.cc
new file mode 100644
index 0000000..628d0d8
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_cl_generator.cc
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2008- Patrick Collison <patrick@collison.ie>
+ * Copyright (c) 2006- Facebook
+ *
+ * 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.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <boost/tokenizer.hpp>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include <string>
+#include <algorithm>
+
+#include "thrift/platform.h"
+#include "t_oop_generator.h"
+using namespace std;
+
+
+/**
+ * Common Lisp code generator.
+ *
+ * @author Patrick Collison <patrick@collison.ie>
+ */
+class t_cl_generator : public t_oop_generator {
+ public:
+  t_cl_generator(
+      t_program* program,
+      const std::map<std::string, std::string>& parsed_options,
+      const std::string& option_string)
+    : t_oop_generator(program)
+  {
+    no_asd = false;
+    system_prefix = "thrift-gen-";
+
+    std::map<std::string, std::string>::const_iterator iter;
+
+    for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if(iter->first.compare("no_asd") == 0) {
+        no_asd = true;
+      } else if (iter->first.compare("sys_pref") == 0) {
+	system_prefix = iter->second;
+      } else {
+        throw "unknown option cl:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cl";
+    copy_options_ = option_string;
+  }
+
+  void init_generator();
+  void close_generator();
+
+  void generate_typedef     (t_typedef*  ttypedef);
+  void generate_enum        (t_enum*     tenum);
+  void generate_const       (t_const*    tconst);
+  void generate_struct      (t_struct*   tstruct);
+  void generate_xception    (t_struct*   txception);
+  void generate_service     (t_service*  tservice);
+  void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_exception_sig(std::ostream& out, t_function* f);
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  std::string cl_autogen_comment();
+  void asdf_def(std::ostream &out);
+  void package_def(std::ostream &out);
+  void package_in(std::ostream &out);
+  std::string generated_package();
+  std::string prefix(std::string name);
+  std::string package_of(t_program* program);
+  std::string package();
+  std::string render_includes();
+
+  std::string type_name(t_type* ttype);
+  std::string typespec (t_type *t);
+  std::string function_signature(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct);
+
+  std::string cl_docstring(std::string raw);
+
+ private:
+
+  int temporary_var;
+  /**
+   * Isolate the variable definitions, as they can require structure definitions
+   */
+  ofstream_with_content_based_conditional_update f_asd_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_vars_;
+
+  std::string copy_options_;
+
+  bool no_asd;
+  std::string system_prefix;
+};
+
+
+void t_cl_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+  string program_dir = get_out_dir() + "/" + program_name_;
+  MKDIR(program_dir.c_str());
+
+  temporary_var = 0;
+
+  string f_types_name = program_dir + "/" + program_name_ + "-types.lisp";
+  string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp";
+
+  f_types_.open(f_types_name.c_str());
+  f_types_ << cl_autogen_comment() << endl;
+  f_vars_.open(f_vars_name.c_str());
+  f_vars_ << cl_autogen_comment() << endl;
+
+  package_def(f_types_);
+  package_in(f_types_);
+  package_in(f_vars_);
+
+  if (!no_asd) {
+    string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd";
+    f_asd_.open(f_asd_name.c_str());
+    f_asd_ << cl_autogen_comment() << endl;
+    asdf_def(f_asd_);
+  }
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_cl_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  result += ":depends-on (:thrift";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    result += " :" + system_prefix + underscore(includes[i]->get_name());
+  }
+  result += ")\n";
+  return result;
+}
+
+string t_cl_generator::package_of(t_program* program) {
+  string prefix = program->get_namespace("cl");
+  return prefix.empty() ? "thrift-generated" : prefix;
+}
+
+string t_cl_generator::package() {
+  return package_of(program_);
+}
+
+string t_cl_generator::prefix(string symbol) {
+  return "\"" + symbol + "\"";
+}
+
+string t_cl_generator::cl_autogen_comment() {
+  return
+    std::string(";;; ") + "Autogenerated by Thrift\n" +
+    ";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
+    ";;; options string: " + copy_options_ + "\n";
+}
+
+string t_cl_generator::cl_docstring(string raw) {
+  replace(raw.begin(), raw.end(), '"', '\'');
+  return raw;
+}
+
+
+void t_cl_generator::close_generator() {
+  f_asd_.close();
+  f_types_.close();
+  f_vars_.close();
+}
+
+string t_cl_generator::generated_package() {
+  return program_->get_namespace("cpp");
+}
+
+void t_cl_generator::asdf_def(std::ostream &out) {
+  out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl;
+  indent_up();
+  out << indent() << render_includes()
+      << indent() << ":serial t" << endl
+      << indent() << ":components ("
+      << "(:file \"" << program_name_ << "-types\") "
+      << "(:file \"" << program_name_ << "-vars\")))" << endl;
+  indent_down();
+}
+
+/***
+ * Generate a package definition. Add use references equivalent to the idl file's include statements.
+ */
+void t_cl_generator::package_def(std::ostream &out) {
+  const vector<t_program*>& includes = program_->get_includes();
+
+  out << "(thrift:def-package :" << package();
+  if ( includes.size() > 0 ) {
+    out << " :use (";
+    for (size_t i = 0; i < includes.size(); ++i) {
+      out << " :" << includes[i]->get_name();
+    }
+    out << ")";
+  }
+  out << ")" << endl << endl;
+}
+
+void t_cl_generator::package_in(std::ostream &out) {
+  out << "(cl:in-package :" << package() << ")" << endl << endl;
+}
+
+/**
+ * Generates a typedef. This is not done in Common Lisp, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_cl_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+void t_cl_generator::generate_enum(t_enum* tenum) {
+  f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  int value = -1;
+
+  indent_up();
+  f_types_ << indent() << "(";
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    value = (*c_iter)->get_value();
+
+    if(c_iter != constants.begin()) f_types_ << endl << indent() << " ";
+
+    f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")";
+  }
+  indent_down();
+  f_types_ << "))" << endl << endl;
+}
+
+/**
+ * Generate a constant value
+ */
+void t_cl_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")"
+          << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_cl_generator::render_const_value(t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  std::ostringstream out;
+  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:
+      out << "\"" << value->get_string() << "\"";
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "t" : "nil");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << (type->is_struct() ? "(make-instance '" : "(make-exception '") <<
+           lowercase(type->get_name()) << " " << endl;
+    indent_up();
+
+    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+
+      out << indent() << ":" << v_iter->first->get_string() << " " <<
+        render_const_value(field_type, v_iter->second) << endl;
+    }
+    out << indent() << ")";
+
+    indent_down();
+  } else if (type->is_map()) {
+    // emit an hash form with both keys and values to be evaluated
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "(thrift:map ";
+    indent_up();
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << endl << indent()
+          << "(cl:cons " << render_const_value(ktype, v_iter->first) << " "
+          << render_const_value(vtype, v_iter->second) << ")";
+    }
+    indent_down();
+    out << indent() << ")";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    if (type->is_set()) {
+      out << "(thrift:set" << endl;
+    } else {
+      out << "(thrift:list" << endl;
+    }
+    indent_up();
+    indent_up();
+    const vector<t_const_value*>& val = value->get_list();
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << indent() << render_const_value(etype, *v_iter) << endl;
+    }
+    out << indent() << ")";
+    indent_down();
+    indent_down();
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+  return out.str();
+}
+
+void t_cl_generator::generate_struct(t_struct* tstruct) {
+  generate_cl_struct(f_types_, tstruct, false);
+}
+
+void t_cl_generator::generate_xception(t_struct* txception) {
+  generate_cl_struct(f_types_, txception, true);
+}
+
+void t_cl_generator::generate_cl_struct_internal(std::ostream& out, t_struct* tstruct, bool is_exception) {
+  (void)is_exception;
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << "(";
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_const_value* value = (*m_iter)->get_value();
+    t_type* type = (*m_iter)->get_type();
+
+    if (m_iter != members.begin()) {
+      out << endl << indent() << " ";
+    }
+    out << "(" << prefix((*m_iter)->get_name()) << " " <<
+        ( (NULL != value) ? render_const_value(type, value) : "nil" ) <<
+        " :id " << (*m_iter)->get_key();
+    if ( type->is_base_type() && "string" == typespec(type) )
+      if ( ((t_base_type*)type)->is_binary() )
+        out << " :type binary";
+      else
+        out << " :type string";
+    else
+      out << " :type " << typespec(type);
+    if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) {
+      out << " :optional t";
+    }
+    if ( (*m_iter)->has_doc()) {
+      out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\"";
+    }
+    out <<")";
+  }
+
+  out << ")";
+}
+
+void t_cl_generator::generate_cl_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) {
+  std::string name = type_name(tstruct);
+  out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") <<
+      prefix(name) << endl;
+  indent_up();
+  if ( tstruct->has_doc() ) {
+    out << indent() ;
+    out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl;
+  }
+  out << indent() ;
+  generate_cl_struct_internal(out, tstruct, is_exception);
+  indent_down();
+  out << ")" << endl << endl;
+}
+
+void t_cl_generator::generate_exception_sig(std::ostream& out, t_function* f) {
+  generate_cl_struct_internal(out, f->get_xceptions(), true);
+}
+
+void t_cl_generator::generate_service(t_service* tservice) {
+  string extends_client;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  if (tservice->get_extends() != NULL) {
+    extends_client = type_name(tservice->get_extends());
+  }
+
+  extends_client = extends_client.empty() ? "nil" : prefix(extends_client);
+
+  f_types_ << "(thrift:def-service " << prefix(service_name_) << " "
+           << extends_client;
+
+  indent_up();
+
+  if ( tservice->has_doc()) {
+      f_types_ << endl << indent()
+               << "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")";
+    }
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_function* function = *f_iter;
+    string fname = function->get_name();
+    string signature = function_signature(function);
+    t_struct* exceptions = function->get_xceptions();
+    const vector<t_field*>& xmembers = exceptions->get_members();
+
+    f_types_ << endl << indent() << "(:method " << prefix(fname);
+    f_types_ << " (" << signature << " "  << typespec((*f_iter)->get_returntype()) << ")";
+    if (xmembers.size() > 0) {
+      f_types_ << endl << indent() << " :exceptions " ;
+      generate_exception_sig(f_types_, function);
+    }
+    if ( (*f_iter)->is_oneway() ) {
+      f_types_ << endl << indent() << " :oneway t";
+    }
+    if ( (*f_iter)->has_doc() ) {
+      f_types_ << endl << indent() << " :documentation \""
+               << cl_docstring((*f_iter)->get_doc()) << "\"";
+  }
+    f_types_ << ")";
+  }
+
+  f_types_ << ")" << endl << endl;
+
+  indent_down();
+}
+
+string t_cl_generator::typespec(t_type *t) {
+  t = get_true_type(t);
+
+  if (t -> is_binary()){
+    return "binary";
+  } else if (t->is_base_type()) {
+    return type_name(t);
+  } else if (t->is_map()) {
+    t_map *m = (t_map*) t;
+    return "(thrift:map " + typespec(m->get_key_type()) + " " +
+      typespec(m->get_val_type()) + ")";
+  } else if (t->is_struct() || t->is_xception()) {
+    return "(struct " + prefix(type_name(t)) + ")";
+  } else if (t->is_list()) {
+    return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")";
+  } else if (t->is_set()) {
+    return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")";
+  } else if (t->is_enum()) {
+    return "(enum \"" + ((t_enum*) t)->get_name() + "\")";
+  } else {
+    throw "Sorry, I don't know how to generate this: " + type_name(t);
+  }
+}
+
+string t_cl_generator::function_signature(t_function* tfunction) {
+  return argument_list(tfunction->get_arglist());
+}
+
+string t_cl_generator::argument_list(t_struct* tstruct) {
+  stringstream res;
+  res << "(";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      res << " ";
+    }
+    res << "(" + prefix((*f_iter)->get_name()) << " " <<
+      typespec((*f_iter)->get_type()) << " " <<
+      (*f_iter)->get_key() <<  ")";
+
+
+  }
+  res << ")";
+  return res.str();
+}
+
+string t_cl_generator::type_name(t_type* ttype) {
+  string prefix = "";
+  t_program* program = ttype->get_program();
+
+  if (program != NULL && program != program_)
+    prefix = package_of(program) == package() ? "" : package_of(program) + ":";
+
+  string name = ttype->get_name();
+
+  if (ttype->is_struct() || ttype->is_xception())
+    name = lowercase(ttype->get_name());
+
+  return prefix + name;
+}
+
+THRIFT_REGISTER_GENERATOR(
+    cl,
+    "Common Lisp",
+    "    no_asd:          Do not define ASDF systems for each generated Thrift program.\n"
+    "    sys_pref=        The prefix to give ASDF system names. Default: thrift-gen-\n")
diff --git a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
index c2f09e8..ac644f5 100644
--- a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc
@@ -109,35 +109,35 @@
                                  bool box_it = false);
 
   void generate_cocoa_struct(t_struct* tstruct, bool is_exception);
-  void generate_cocoa_struct_interface(std::ofstream& out,
+  void generate_cocoa_struct_interface(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false);
-  void generate_cocoa_struct_implementation(std::ofstream& out,
+  void generate_cocoa_struct_implementation(std::ostream& out,
                                             t_struct* tstruct,
                                             bool is_xception = false,
                                             bool is_result = false);
-  void generate_cocoa_struct_initializer_signature(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_init_with_coder_method(ofstream& out,
+  void generate_cocoa_struct_initializer_signature(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_init_with_coder_method(ostream& out,
                                                     t_struct* tstruct,
                                                     bool is_exception);
-  void generate_cocoa_struct_encode_with_coder_method(ofstream& out,
+  void generate_cocoa_struct_encode_with_coder_method(ostream& out,
                                                       t_struct* tstruct,
                                                       bool is_exception);
-  void generate_cocoa_struct_copy_method(ofstream& out,
+  void generate_cocoa_struct_copy_method(ostream& out,
                                          t_struct* tstruct,
                                          bool is_exception);
-  void generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_is_equal_method(ofstream& out,
+  void generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_is_equal_method(ostream& out,
                                              t_struct* tstruct,
                                              bool is_exception);
-  void generate_cocoa_struct_field_accessor_implementations(std::ofstream& out,
+  void generate_cocoa_struct_field_accessor_implementations(std::ostream& out,
                                                             t_struct* tstruct,
                                                             bool is_exception);
-  void generate_cocoa_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_cocoa_struct_description(std::ofstream& out, t_struct* tstruct);
+  void generate_cocoa_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_validator(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_description(std::ostream& out, t_struct* tstruct);
 
   std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
   std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
@@ -147,29 +147,29 @@
    * Service-level generation functions
    */
 
-  void generate_cocoa_service_protocol(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_async_protocol(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_protocol(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_async_protocol(std::ostream& out, t_service* tservice);
 
-  void generate_cocoa_service_client_interface(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_client_async_interface(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_client_interface(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_interface(std::ostream& out, t_service* tservice);
 
-  void generate_cocoa_service_client_send_function_implementation(ofstream& out,
+  void generate_cocoa_service_client_send_function_implementation(ostream& out,
                                                                   t_service* tservice,
                                                                   t_function* tfunction,
                                                                   bool needs_protocol);
-  void generate_cocoa_service_client_send_function_invocation(ofstream& out, t_function* tfunction);
-  void generate_cocoa_service_client_send_async_function_invocation(ofstream& out,
+  void generate_cocoa_service_client_send_function_invocation(ostream& out, t_function* tfunction);
+  void generate_cocoa_service_client_send_async_function_invocation(ostream& out,
                                                                     t_function* tfunction,
                                                                     string failureBlockName);
-  void generate_cocoa_service_client_recv_function_implementation(ofstream& out,
+  void generate_cocoa_service_client_recv_function_implementation(ostream& out,
                                                                   t_service* tservice,
                                                                   t_function* tfunction,
                                                                   bool needs_protocol);
-  void generate_cocoa_service_client_implementation(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_client_async_implementation(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_client_implementation(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_implementation(std::ostream& out, t_service* tservice);
 
-  void generate_cocoa_service_server_interface(std::ofstream& out, t_service* tservice);
-  void generate_cocoa_service_server_implementation(std::ofstream& out, t_service* tservice);
+  void generate_cocoa_service_server_interface(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_server_implementation(std::ostream& out, t_service* tservice);
   void generate_cocoa_service_helpers(t_service* tservice);
   void generate_service_client(t_service* tservice);
   void generate_service_server(t_service* tservice);
@@ -179,34 +179,34 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string fieldName);
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string fieldName);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string fieldName = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string fieldName = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out,
+  void generate_serialize_list_element(std::ostream& out,
                                        t_list* tlist,
                                        std::string index,
                                        std::string listName);
@@ -238,6 +238,12 @@
   std::string getter_name(string field_name);
   std::string setter_name(string field_name);
 
+  bool type_can_be_copy(t_type* ttype) {
+    ttype = get_true_type(ttype);
+    
+    return ttype->is_string();
+  }
+  
   bool type_can_be_null(t_type* ttype) {
     ttype = get_true_type(ttype);
 
@@ -254,8 +260,8 @@
    * File streams
    */
 
-  std::ofstream f_header_;
-  std::ofstream f_impl_;
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_impl_;
 
   bool log_unexpected_;
   bool validate_required_;
@@ -568,7 +574,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_interface(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_interface(ostream& out,
                                                         t_struct* tstruct,
                                                         bool is_exception) {
 
@@ -618,7 +624,7 @@
  * Generate signature for initializer of struct with a parameter for
  * each field.
  */
-void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ostream& out,
                                                                     t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
@@ -641,7 +647,7 @@
  * Generate the initWithCoder method for this struct so it's compatible with
  * the NSCoding protocol
  */
-void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ostream& out,
                                                                      t_struct* tstruct,
                                                                      bool is_exception) {
 
@@ -713,7 +719,7 @@
  * Generate the encodeWithCoder method for this struct so it's compatible with
  * the NSCoding protocol
  */
-void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ostream& out,
                                                                        t_struct* tstruct,
                                                                        bool is_exception) {
 
@@ -780,7 +786,7 @@
 /**
  * Generate the copy method for this struct
  */
-void t_cocoa_generator::generate_cocoa_struct_copy_method(ofstream& out, t_struct* tstruct, bool is_exception) {
+void t_cocoa_generator::generate_cocoa_struct_copy_method(ostream& out, t_struct* tstruct, bool is_exception) {
   out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl;
   scope_up(out);
 
@@ -815,7 +821,7 @@
 /**
  * Generate the hash method for this struct
  */
-void t_cocoa_generator::generate_cocoa_struct_hash_method(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct) {
   indent(out) << "- (NSUInteger) hash" << endl;
   scope_up(out);
   out << indent() << "NSUInteger hash = 17;" << endl;
@@ -846,7 +852,7 @@
 /**
  * Generate the isEqual method for this struct
  */
-void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ofstream& out, t_struct* tstruct, bool is_exception) {
+void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ostream& out, t_struct* tstruct, bool is_exception) {
   indent(out) << "- (BOOL) isEqual: (id) anObject" << endl;
   scope_up(out);
 
@@ -913,7 +919,7 @@
  * @param is_exception Is this an exception?
  * @param is_result    If this is a result it needs a different writer
  */
-void t_cocoa_generator::generate_cocoa_struct_implementation(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_implementation(ostream& out,
                                                              t_struct* tstruct,
                                                              bool is_exception,
                                                              bool is_result) {
@@ -1017,7 +1023,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_reader(ostream& out, t_struct* tstruct) {
   out << "- (BOOL) read: (id <TProtocol>) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl;
   scope_up(out);
 
@@ -1111,7 +1117,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
   indent_up();
 
@@ -1162,7 +1168,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_result_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
   indent_up();
 
@@ -1225,7 +1231,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_validator(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_validator(ostream& out, t_struct* tstruct) {
   out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl;
   indent_up();
 
@@ -1259,7 +1265,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ofstream& out,
+void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ostream& out,
                                                                              t_struct* tstruct,
                                                                              bool is_exception) {
   (void)is_exception;
@@ -1298,7 +1304,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_cocoa_generator::generate_cocoa_struct_description(ofstream& out, t_struct* tstruct) {
+void t_cocoa_generator::generate_cocoa_struct_description(ostream& out, t_struct* tstruct) {
 
   // Allow use of debugDescription so the app can add description via a cateogory/extension
   if (debug_descriptions_) {
@@ -1428,7 +1434,7 @@
  *
  * @param tservice The service to generate a protocol definition for
  */
-void t_cocoa_generator::generate_cocoa_service_protocol(ofstream& out, t_service* tservice) {
+void t_cocoa_generator::generate_cocoa_service_protocol(ostream& out, t_service* tservice) {
   out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " <NSObject>" << endl;
 
   vector<t_function*> functions = tservice->get_functions();
@@ -1452,7 +1458,7 @@
  *
  * @param tservice The service to generate a protocol definition for
  */
-void t_cocoa_generator::generate_cocoa_service_async_protocol(ofstream& out, t_service* tservice) {
+void t_cocoa_generator::generate_cocoa_service_async_protocol(ostream& out, t_service* tservice) {
   out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async"
       << " <NSObject>" << endl;
 
@@ -1472,7 +1478,7 @@
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_cocoa_generator::generate_cocoa_service_client_interface(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_client_interface(ostream& out,
                                                                 t_service* tservice) {
   out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <"
       << cocoa_prefix_ << tservice->get_name() << "> " << endl;
@@ -1488,7 +1494,7 @@
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_cocoa_generator::generate_cocoa_service_client_async_interface(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_client_async_interface(ostream& out,
                                                                       t_service* tservice) {
   out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <"
       << cocoa_prefix_ << tservice->get_name() << "Async> " << endl
@@ -1506,7 +1512,7 @@
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_cocoa_generator::generate_cocoa_service_server_interface(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_server_interface(ostream& out,
                                                                 t_service* tservice) {
   out << "@interface " << cocoa_prefix_ << tservice->get_name()
       << "Processor : NSObject <TProcessor> " << endl;
@@ -1519,7 +1525,7 @@
 }
 
 void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation(
-    ofstream& out,
+    ostream& out,
     t_service *tservice,
     t_function* tfunction,
     bool needs_protocol) {
@@ -1577,7 +1583,7 @@
 }
 
 void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation(
-    ofstream& out,
+    ostream& out,
     t_service* tservice,
     t_function* tfunction,
     bool needs_protocol) {
@@ -1666,7 +1672,7 @@
  * @param tfunction The service to generate an implementation for
  */
 void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation(
-                                                                               ofstream& out,
+                                                                               ostream& out,
                                                                                t_function* tfunction) {
 
   t_struct* arg_struct = tfunction->get_arglist();
@@ -1696,7 +1702,7 @@
  * @param tfunction The service to generate an implementation for
  */
 void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation(
-                                                                                     ofstream& out,
+                                                                                     ostream& out,
                                                                                      t_function* tfunction,
                                                                                      string failureBlockName) {
 
@@ -1730,7 +1736,7 @@
  *
  * @param tservice The service to generate an implementation for
  */
-void t_cocoa_generator::generate_cocoa_service_client_implementation(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_client_implementation(ostream& out,
                                                                      t_service* tservice) {
 
   string name = cocoa_prefix_ + tservice->get_name() + "Client";
@@ -1814,7 +1820,7 @@
  *
  * @param tservice The service to generate an implementation for
  */
-void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ostream& out,
                                                                            t_service* tservice) {
 
   string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync";
@@ -1974,7 +1980,7 @@
  *
  * @param tservice The service to generate an implementation for
  */
-void t_cocoa_generator::generate_cocoa_service_server_implementation(ofstream& out,
+void t_cocoa_generator::generate_cocoa_service_server_implementation(ostream& out,
                                                                      t_service* tservice) {
 
   string name = cocoa_prefix_ + tservice->get_name() + "Processor";
@@ -2150,7 +2156,7 @@
  * @param tfield The field
  * @param fieldName The variable name for this field
  */
-void t_cocoa_generator::generate_deserialize_field(ofstream& out,
+void t_cocoa_generator::generate_deserialize_field(ostream& out,
                                                    t_field* tfield,
                                                    string fieldName) {
   t_type* type = get_true_type(tfield->get_type());
@@ -2216,7 +2222,7 @@
 /**
  * Generates an unserializer for a struct, allocates the struct and invokes read:
  */
-void t_cocoa_generator::generate_deserialize_struct(ofstream& out,
+void t_cocoa_generator::generate_deserialize_struct(ostream& out,
                                                     t_struct* tstruct,
                                                     string fieldName) {
   indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true)
@@ -2227,7 +2233,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_cocoa_generator::generate_deserialize_container(ofstream& out,
+void t_cocoa_generator::generate_deserialize_container(ostream& out,
                                                        t_type* ttype,
                                                        string fieldName) {
   string size = tmp("_size");
@@ -2348,7 +2354,7 @@
 /**
  * Generates code to deserialize a map element
  */
-void t_cocoa_generator::generate_deserialize_map_element(ofstream& out,
+void t_cocoa_generator::generate_deserialize_map_element(ostream& out,
                                                          t_map* tmap,
                                                          string fieldName) {
   string key = tmp("_key");
@@ -2368,7 +2374,7 @@
 /**
  * Deserializes a set element
  */
-void t_cocoa_generator::generate_deserialize_set_element(ofstream& out,
+void t_cocoa_generator::generate_deserialize_set_element(ostream& out,
                                                          t_set* tset,
                                                          string fieldName) {
   string elem = tmp("_elem");
@@ -2383,7 +2389,7 @@
 /**
  * Deserializes a list element
  */
-void t_cocoa_generator::generate_deserialize_list_element(ofstream& out,
+void t_cocoa_generator::generate_deserialize_list_element(ostream& out,
                                                           t_list* tlist,
                                                           string fieldName) {
   string elem = tmp("_elem");
@@ -2401,7 +2407,7 @@
  * @param tfield The field to serialize
  * @param fieldName Name to of the variable holding the field
  */
-void t_cocoa_generator::generate_serialize_field(ofstream& out, t_field* tfield, string fieldName) {
+void t_cocoa_generator::generate_serialize_field(ostream& out, t_field* tfield, string fieldName) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2468,7 +2474,7 @@
  * @param tstruct The struct to serialize
  * @param fieldName Name of variable holding struct
  */
-void t_cocoa_generator::generate_serialize_struct(ofstream& out,
+void t_cocoa_generator::generate_serialize_struct(ostream& out,
                                                   t_struct* tstruct,
                                                   string fieldName) {
   (void)tstruct;
@@ -2481,7 +2487,7 @@
  * @param ttype  The type of container
  * @param fieldName Name of variable holding container
  */
-void t_cocoa_generator::generate_serialize_container(ofstream& out,
+void t_cocoa_generator::generate_serialize_container(ostream& out,
                                                      t_type* ttype,
                                                      string fieldName) {
   scope_up(out);
@@ -2547,7 +2553,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_cocoa_generator::generate_serialize_map_element(ofstream& out,
+void t_cocoa_generator::generate_serialize_map_element(ostream& out,
                                                        t_map* tmap,
                                                        string key,
                                                        string mapName) {
@@ -2560,7 +2566,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_cocoa_generator::generate_serialize_set_element(ofstream& out,
+void t_cocoa_generator::generate_serialize_set_element(ostream& out,
                                                        t_set* tset,
                                                        string elementName) {
   t_field efield(tset->get_elem_type(), elementName);
@@ -2570,7 +2576,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_cocoa_generator::generate_serialize_list_element(ofstream& out,
+void t_cocoa_generator::generate_serialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string index,
                                                         string listName) {
@@ -2733,8 +2739,8 @@
     indent(out);
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     if (defval)
       out << type_name(type) << " ";
     out << name << " = [" << type_name(type, true) << " new];"
@@ -2758,8 +2764,8 @@
     indent(mapout);
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     if (defval)
       mapout << type_name(type) << " ";
     mapout << name << " = @{";
@@ -2904,8 +2910,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     if (val.size() > 0)
       render << "[[" << type_name(type, true) << " alloc] initWith";
     else
@@ -2937,8 +2943,8 @@
     render << "[[NSDictionary alloc] initWithObjectsAndKeys: ";
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     bool first = true;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(name, ktype, v_iter->first, true);
@@ -3011,7 +3017,9 @@
   std::ostringstream render;
   render << "@property (";
 
-  if (type_can_be_null(tfield->get_type())) {
+  if (type_can_be_copy(tfield->get_type())) {
+    render << "copy, ";
+  } else if (type_can_be_null(tfield->get_type())) {
     render << "strong, ";
   } else {
     render << "assign, ";
diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
index 1c93957..cf30363 100644
--- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
@@ -24,7 +24,9 @@
 #include <cassert>
 
 #include <fstream>
+#include <iomanip>
 #include <iostream>
+#include <limits>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -110,8 +112,8 @@
 
   void generate_typedef(t_typedef* ttypedef);
   void generate_enum(t_enum* tenum);
-  void generate_enum_ostream_operator_decl(std::ofstream& out, t_enum* tenum);
-  void generate_enum_ostream_operator(std::ofstream& out, t_enum* tenum);
+  void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum);
+  void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum);
   void generate_forward_declaration(t_struct* tstruct);
   void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); }
   void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); }
@@ -119,13 +121,13 @@
 
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
-  std::string render_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value);
+  std::string render_const_value(std::ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
 
-  void generate_struct_declaration(std::ofstream& out,
+  void generate_struct_declaration(std::ostream& out,
                                    t_struct* tstruct,
                                    bool is_exception = false,
                                    bool pointers = false,
@@ -133,26 +135,26 @@
                                    bool write = true,
                                    bool swap = false,
                                    bool is_user_struct = false);
-  void generate_struct_definition(std::ofstream& out,
-                                  std::ofstream& force_cpp_out,
+  void generate_struct_definition(std::ostream& out,
+                                  std::ostream& force_cpp_out,
                                   t_struct* tstruct,
                                   bool setters = true,
                                   bool is_user_struct = false);
-  void generate_copy_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_move_constructor(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_constructor_helper(std::ofstream& out,
+  void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_constructor_helper(std::ostream& out,
                                    t_struct* tstruct,
                                    bool is_excpetion,
                                    bool is_move);
-  void generate_assignment_operator(std::ofstream& out, t_struct* tstruct);
-  void generate_move_assignment_operator(std::ofstream& out, t_struct* tstruct);
-  void generate_assignment_helper(std::ofstream& out, t_struct* tstruct, bool is_move);
-  void generate_struct_reader(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_result_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false);
-  void generate_struct_swap(std::ofstream& out, t_struct* tstruct);
-  void generate_struct_print_method(std::ofstream& out, t_struct* tstruct);
-  void generate_exception_what_method(std::ofstream& out, t_struct* tstruct);
+  void generate_assignment_operator(std::ostream& out, t_struct* tstruct);
+  void generate_move_assignment_operator(std::ostream& out, t_struct* tstruct);
+  void generate_assignment_helper(std::ostream& out, t_struct* tstruct, bool is_move);
+  void generate_struct_reader(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_writer(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_result_writer(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_swap(std::ostream& out, t_struct* tstruct);
+  void generate_struct_print_method(std::ostream& out, t_struct* tstruct);
+  void generate_exception_what_method(std::ostream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
@@ -177,45 +179,45 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   std::string suffix = "");
 
-  void generate_deserialize_struct(std::ofstream& out,
+  void generate_deserialize_struct(std::ostream& out,
                                    t_struct* tstruct,
                                    std::string prefix = "",
                                    bool pointer = false);
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix,
                                          bool push_back,
                                          std::string index);
 
-  void generate_serialize_field(std::ofstream& out,
+  void generate_serialize_field(std::ostream& out,
                                 t_field* tfield,
                                 std::string prefix = "",
                                 std::string suffix = "");
 
-  void generate_serialize_struct(std::ofstream& out,
+  void generate_serialize_struct(std::ostream& out,
                                  t_struct* tstruct,
                                  std::string prefix = "",
                                  bool pointer = false);
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out, t_map* tmap, std::string iter);
+  void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
   void generate_function_call(ostream& out,
                               t_function* tfunction,
@@ -246,16 +248,16 @@
   std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false);
   std::string type_to_enum(t_type* ttype);
 
-  void generate_enum_constant_list(std::ofstream& f,
+  void generate_enum_constant_list(std::ostream& f,
                                    const vector<t_enum_value*>& constants,
                                    const char* prefix,
                                    const char* suffix,
                                    bool include_values);
 
-  void generate_struct_ostream_operator_decl(std::ofstream& f, t_struct* tstruct);
-  void generate_struct_ostream_operator(std::ofstream& f, t_struct* tstruct);
-  void generate_struct_print_method_decl(std::ofstream& f, t_struct* tstruct);
-  void generate_exception_what_method_decl(std::ofstream& f,
+  void generate_struct_ostream_operator_decl(std::ostream& f, t_struct* tstruct);
+  void generate_struct_ostream_operator(std::ostream& f, t_struct* tstruct);
+  void generate_struct_print_method_decl(std::ostream& f, t_struct* tstruct);
+  void generate_exception_what_method_decl(std::ostream& f,
                                            t_struct* tstruct,
                                            bool external = false);
 
@@ -358,12 +360,12 @@
    * function.
    */
 
-  std::ofstream f_types_;
-  std::ofstream f_types_impl_;
-  std::ofstream f_types_tcc_;
-  std::ofstream f_header_;
-  std::ofstream f_service_;
-  std::ofstream f_service_tcc_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_types_impl_;
+  ofstream_with_content_based_conditional_update f_types_tcc_;
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_service_;
+  ofstream_with_content_based_conditional_update f_service_tcc_;
 
   // The ProcessorGenerator is used to generate parts of the code,
   // so it needs access to many of our protected members and methods.
@@ -384,7 +386,7 @@
 
   // Make output file
   string f_types_name = get_out_dir() + program_name_ + "_types.h";
-  f_types_.open(f_types_name.c_str());
+  f_types_.open(f_types_name);
 
   string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp";
   f_types_impl_.open(f_types_impl_name.c_str());
@@ -417,7 +419,8 @@
            << "#include <thrift/transport/TTransport.h>" << endl
            << endl;
   // Include C++xx compatibility header
-  f_types_ << "#include <thrift/stdcxx.h>" << endl;
+  f_types_ << "#include <functional>" << endl;
+  f_types_ << "#include <memory>" << endl;
 
   // Include other Thrift includes
   const vector<t_program*>& includes = program_->get_includes();
@@ -503,7 +506,7 @@
            << ttypedef->get_symbolic() << ";" << endl << endl;
 }
 
-void t_cpp_generator::generate_enum_constant_list(std::ofstream& f,
+void t_cpp_generator::generate_enum_constant_list(std::ostream& f,
                                                   const vector<t_enum_value*>& constants,
                                                   const char* prefix,
                                                   const char* suffix,
@@ -583,7 +586,7 @@
   generate_enum_ostream_operator(f_types_impl_, tenum);
 }
 
-void t_cpp_generator::generate_enum_ostream_operator_decl(std::ofstream& out, t_enum* tenum) {
+void t_cpp_generator::generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum) {
 
   out << "std::ostream& operator<<(std::ostream& out, const ";
   if (gen_pure_enums_) {
@@ -595,7 +598,7 @@
   out << endl;
 }
 
-void t_cpp_generator::generate_enum_ostream_operator(std::ofstream& out, t_enum* tenum) {
+void t_cpp_generator::generate_enum_ostream_operator(std::ostream& out, t_enum* tenum) {
 
   // If we've been told the consuming application will provide an ostream
   // operator definition then we only make a declaration:
@@ -633,12 +636,12 @@
  */
 void t_cpp_generator::generate_consts(std::vector<t_const*> consts) {
   string f_consts_name = get_out_dir() + program_name_ + "_constants.h";
-  ofstream f_consts;
-  f_consts.open(f_consts_name.c_str());
+  ofstream_with_content_based_conditional_update f_consts;
+  f_consts.open(f_consts_name);
 
   string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp";
-  ofstream f_consts_impl;
-  f_consts_impl.open(f_consts_impl_name.c_str());
+  ofstream_with_content_based_conditional_update f_consts_impl;
+  f_consts_impl.open(f_consts_impl_name);
 
   // Print header
   f_consts << autogen_comment();
@@ -682,6 +685,7 @@
   f_consts.close();
 
   f_consts_impl << endl << ns_close_ << endl << endl;
+  f_consts_impl.close();
 }
 
 /**
@@ -689,7 +693,7 @@
  * is NOT performed in this function as it is always run beforehand using the
  * validate_types method in main.cc
  */
-void t_cpp_generator::print_const_value(ofstream& out,
+void t_cpp_generator::print_const_value(ostream& out,
                                         string name,
                                         t_type* type,
                                         t_const_value* value) {
@@ -703,8 +707,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     bool is_nonrequired_field = false;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
@@ -728,8 +732,8 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
       string val = render_const_value(out, name, vtype, v_iter->second);
@@ -762,7 +766,7 @@
 /**
  *
  */
-string t_cpp_generator::render_const_value(ofstream& out,
+string t_cpp_generator::render_const_value(ostream& out,
                                            string name,
                                            t_type* type,
                                            t_const_value* value) {
@@ -788,9 +792,9 @@
       break;
     case t_base_type::TYPE_DOUBLE:
       if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << value->get_integer();
+        render << "static_cast<double>(" << value->get_integer() << ")";
       } else {
-        render << value->get_double();
+        render << emit_double_as_string(value->get_double());
       }
       break;
     default:
@@ -824,7 +828,7 @@
   generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true);
   generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true);
 
-  std::ofstream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
+  std::ostream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
   generate_struct_reader(out, tstruct);
   generate_struct_writer(out, tstruct);
   generate_struct_swap(f_types_impl_, tstruct);
@@ -846,13 +850,13 @@
   }
 }
 
-void t_cpp_generator::generate_copy_constructor(ofstream& out,
+void t_cpp_generator::generate_copy_constructor(ostream& out,
                                                 t_struct* tstruct,
                                                 bool is_exception) {
   generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false);
 }
 
-void t_cpp_generator::generate_move_constructor(ofstream& out,
+void t_cpp_generator::generate_move_constructor(ostream& out,
                                                 t_struct* tstruct,
                                                 bool is_exception) {
   generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true);
@@ -868,7 +872,7 @@
 }
 }
 
-void t_cpp_generator::generate_constructor_helper(ofstream& out,
+void t_cpp_generator::generate_constructor_helper(ostream& out,
                                                   t_struct* tstruct,
                                                   bool is_exception,
                                                   bool is_move) {
@@ -911,15 +915,15 @@
   indent(out) << "}" << endl;
 }
 
-void t_cpp_generator::generate_assignment_operator(ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_assignment_operator(ostream& out, t_struct* tstruct) {
   generate_assignment_helper(out, tstruct, /*is_move=*/false);
 }
 
-void t_cpp_generator::generate_move_assignment_operator(ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_move_assignment_operator(ostream& out, t_struct* tstruct) {
   generate_assignment_helper(out, tstruct, /*is_move=*/true);
 }
 
-void t_cpp_generator::generate_assignment_helper(ofstream& out, t_struct* tstruct, bool is_move) {
+void t_cpp_generator::generate_assignment_helper(ostream& out, t_struct* tstruct, bool is_move) {
   std::string tmp_name = tmp("other");
 
   indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=(";
@@ -962,7 +966,7 @@
  * @param out Output stream
  * @param tstruct The struct
  */
-void t_cpp_generator::generate_struct_declaration(ofstream& out,
+void t_cpp_generator::generate_struct_declaration(ostream& out,
                                                   t_struct* tstruct,
                                                   bool is_exception,
                                                   bool pointers,
@@ -1094,7 +1098,7 @@
   }
 
   if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
-    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
+    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() noexcept;" << endl;
   }
 
   // Declare all fields
@@ -1116,7 +1120,7 @@
       continue;
     }
     if (is_reference((*m_iter))) {
-      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<"
+      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::std::shared_ptr<"
           << type_name((*m_iter)->get_type(), false, false) << ">";
       out << " val);" << endl;
     } else {
@@ -1211,8 +1215,8 @@
   }
 }
 
-void t_cpp_generator::generate_struct_definition(ofstream& out,
-                                                 ofstream& force_cpp_out,
+void t_cpp_generator::generate_struct_definition(ostream& out,
+                                                 ostream& force_cpp_out,
                                                  t_struct* tstruct,
                                                  bool setters,
                                                  bool is_user_struct) {
@@ -1223,7 +1227,7 @@
   // Destructor
   if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
     force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
-                  << "() throw() {" << endl;
+                  << "() noexcept {" << endl;
     indent_up();
 
     indent_down();
@@ -1236,7 +1240,7 @@
       if (is_reference((*m_iter))) {
         std::string type = type_name((*m_iter)->get_type());
         out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
-            << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<"
+            << (*m_iter)->get_name() << "(::std::shared_ptr<"
             << type_name((*m_iter)->get_type(), false, false) << ">";
         out << " val) {" << endl;
       } else {
@@ -1269,7 +1273,7 @@
  * @param out Stream to write to
  * @param tstruct The struct
  */
-void t_cpp_generator::generate_struct_reader(ofstream& out, t_struct* tstruct, bool pointers) {
+void t_cpp_generator::generate_struct_reader(ostream& out, t_struct* tstruct, bool pointers) {
   if (gen_templates_) {
     out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
         << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
@@ -1392,7 +1396,7 @@
  * @param out Stream to write to
  * @param tstruct The struct
  */
-void t_cpp_generator::generate_struct_writer(ofstream& out, t_struct* tstruct, bool pointers) {
+void t_cpp_generator::generate_struct_writer(ostream& out, t_struct* tstruct, bool pointers) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_sorted_members();
   vector<t_field*>::const_iterator f_iter;
@@ -1458,7 +1462,7 @@
  * @param out Output stream
  * @param tstruct The result struct
  */
-void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+void t_cpp_generator::generate_struct_result_writer(ostream& out,
                                                     t_struct* tstruct,
                                                     bool pointers) {
   string name = tstruct->get_name();
@@ -1522,7 +1526,7 @@
  * @param out Stream to write to
  * @param tstruct The struct
  */
-void t_cpp_generator::generate_struct_swap(ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) {
   out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
       << " &b) {" << endl;
   indent_up();
@@ -1559,14 +1563,14 @@
   out << endl;
 }
 
-void t_cpp_generator::generate_struct_ostream_operator_decl(std::ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_struct_ostream_operator_decl(std::ostream& out, t_struct* tstruct) {
   out << "std::ostream& operator<<(std::ostream& out, const "
       << tstruct->get_name()
       << "& obj);" << endl;
   out << endl;
 }
 
-void t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_struct_ostream_operator(std::ostream& out, t_struct* tstruct) {
   if (!has_custom_ostream(tstruct)) {
     // thrift defines this behavior
     out << "std::ostream& operator<<(std::ostream& out, const "
@@ -1580,7 +1584,7 @@
   }
 }
 
-void t_cpp_generator::generate_struct_print_method_decl(std::ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_struct_print_method_decl(std::ostream& out, t_struct* tstruct) {
   out << "void ";
   if (tstruct) {
     out << tstruct->get_name() << "::";
@@ -1588,44 +1592,44 @@
   out << "printTo(std::ostream& out) const";
 }
 
-void t_cpp_generator::generate_exception_what_method_decl(std::ofstream& out,
+void t_cpp_generator::generate_exception_what_method_decl(std::ostream& out,
                                                           t_struct* tstruct,
                                                           bool external) {
   out << "const char* ";
   if (external) {
     out << tstruct->get_name() << "::";
   }
-  out << "what() const throw()";
+  out << "what() const noexcept";
 }
 
 namespace struct_ostream_operator_generator {
-void generate_required_field_value(std::ofstream& out, const t_field* field) {
+void generate_required_field_value(std::ostream& out, const t_field* field) {
   out << " << to_string(" << field->get_name() << ")";
 }
 
-void generate_optional_field_value(std::ofstream& out, const t_field* field) {
+void generate_optional_field_value(std::ostream& out, const t_field* field) {
   out << "; (__isset." << field->get_name() << " ? (out";
   generate_required_field_value(out, field);
   out << ") : (out << \"<null>\"))";
 }
 
-void generate_field_value(std::ofstream& out, const t_field* field) {
+void generate_field_value(std::ostream& out, const t_field* field) {
   if (field->get_req() == t_field::T_OPTIONAL)
     generate_optional_field_value(out, field);
   else
     generate_required_field_value(out, field);
 }
 
-void generate_field_name(std::ofstream& out, const t_field* field) {
+void generate_field_name(std::ostream& out, const t_field* field) {
   out << "\"" << field->get_name() << "=\"";
 }
 
-void generate_field(std::ofstream& out, const t_field* field) {
+void generate_field(std::ostream& out, const t_field* field) {
   generate_field_name(out, field);
   generate_field_value(out, field);
 }
 
-void generate_fields(std::ofstream& out,
+void generate_fields(std::ostream& out,
                      const vector<t_field*>& fields,
                      const std::string& indent) {
   const vector<t_field*>::const_iterator beg = fields.begin();
@@ -1647,7 +1651,7 @@
 /**
  * Generates operator<<
  */
-void t_cpp_generator::generate_struct_print_method(std::ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_struct_print_method(std::ostream& out, t_struct* tstruct) {
   out << indent();
   generate_struct_print_method_decl(out, tstruct);
   out << " {" << endl;
@@ -1666,7 +1670,7 @@
 /**
  * Generates what() method for exceptions
  */
-void t_cpp_generator::generate_exception_what_method(std::ofstream& out, t_struct* tstruct) {
+void t_cpp_generator::generate_exception_what_method(std::ostream& out, t_struct* tstruct) {
   out << indent();
   generate_exception_what_method_decl(out, tstruct, true);
   out << " {" << endl;
@@ -1714,8 +1718,9 @@
   f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl
             << endl;
   if (gen_cob_style_) {
-    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl << // TMemoryBuffer
-        "#include <thrift/stdcxx.h>" << endl
+    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl // TMemoryBuffer
+              << "#include <functional>" << endl 
+              << "#include <memory>" << endl
               << "namespace apache { namespace thrift { namespace async {" << endl
               << "class TAsyncChannel;" << endl << "}}}" << endl;
   }
@@ -1796,7 +1801,7 @@
     if (!gen_no_skeleton_) {
       generate_service_async_skeleton(tservice);
     }
-   
+
   }
 
   f_header_ << "#ifdef _MSC_VER\n"
@@ -1833,7 +1838,7 @@
 void t_cpp_generator::generate_service_helpers(t_service* tservice) {
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
 
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     t_struct* ts = (*f_iter)->get_arglist();
@@ -1965,7 +1970,7 @@
   f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {"
             << endl << " public:" << endl;
   indent_up();
-  f_header_ << indent() << singleton_factory_name << "(const ::apache::thrift::stdcxx::shared_ptr<" << service_if_name
+  f_header_ << indent() << singleton_factory_name << "(const ::std::shared_ptr<" << service_if_name
             << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~"
             << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual "
             << service_if_name << "* getHandler("
@@ -1973,7 +1978,7 @@
             << "  return iface_.get();" << endl << indent() << "}" << endl << indent()
             << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl;
 
-  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << service_if_name
+  f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr<" << service_if_name
             << "> iface_;" << endl;
 
   indent_down();
@@ -2069,7 +2074,7 @@
 
   string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
 
-  ofstream f_skeleton;
+  ofstream_with_content_based_conditional_update f_skeleton;
   f_skeleton.open(f_skeleton_name.c_str());
   f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous"
              << endl << "// interface into an asynchronous interface. You should copy it to another"
@@ -2143,7 +2148,7 @@
     extends_multiface = ", public " + extends + "Multiface";
   }
 
-  string list_type = string("std::vector<apache::thrift::stdcxx::shared_ptr<") + service_name_ + "If> >";
+  string list_type = string("std::vector<std::shared_ptr<") + service_name_ + "If> >";
 
   // Generate the header portion
   f_header_ << "class " << service_name_ << "Multiface : "
@@ -2154,7 +2159,7 @@
             << "& ifaces) : ifaces_(ifaces) {" << endl;
   if (!extends.empty()) {
     f_header_ << indent()
-              << "  std::vector<apache::thrift::stdcxx::shared_ptr<" + service_name_ + "If> >::iterator iter;"
+              << "  std::vector<std::shared_ptr<" + service_name_ + "If> >::iterator iter;"
               << endl << indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {"
               << endl << indent() << "    " << extends << "Multiface::add(*iter);" << endl
               << indent() << "  }" << endl;
@@ -2167,7 +2172,7 @@
   f_header_ << " protected:" << endl;
   indent_up();
   f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_
-            << "Multiface() {}" << endl << indent() << "void add(::apache::thrift::stdcxx::shared_ptr<"
+            << "Multiface() {}" << endl << indent() << "void add(::std::shared_ptr<"
             << service_name_ << "If> iface) {" << endl;
   if (!extends.empty()) {
     f_header_ << indent() << "  " << extends << "Multiface::add(iface);" << endl;
@@ -2237,7 +2242,7 @@
     ifstyle = "CobCl";
   }
 
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
   string template_header, template_suffix, short_suffix, protocol_type, _this;
   string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory";
   if (gen_templates_) {
@@ -2249,7 +2254,7 @@
   } else {
     protocol_type = "::apache::thrift::protocol::TProtocol";
   }
-  string prot_ptr = "apache::thrift::stdcxx::shared_ptr< " + protocol_type + ">";
+  string prot_ptr = "std::shared_ptr< " + protocol_type + ">";
   string client_suffix = "Client" + template_suffix;
   string if_suffix = "If";
   if (style == "Cob") {
@@ -2326,18 +2331,18 @@
     // Note that these are not currently templated for simplicity.
     // TODO(simpkins): should they be templated?
     f_header_ << indent()
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {"
+              << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {"
               << endl << indent() << "  return " << _this << "piprot_;" << endl << indent() << "}"
               << endl;
 
     f_header_ << indent()
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {"
+              << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {"
               << endl << indent() << "  return " << _this << "poprot_;" << endl << indent() << "}"
               << endl;
 
   } else /* if (style == "Cob") */ {
     f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "("
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, "
+              << "std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, "
               << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl;
     if (extends.empty()) {
       f_header_ << indent() << "  channel_(channel)," << endl << indent()
@@ -2347,9 +2352,9 @@
       if (gen_templates_) {
         // TProtocolFactory classes return generic TProtocol pointers.
         // We have to dynamic cast to the Protocol_ type we are expecting.
-        f_header_ << indent() << "  piprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>("
+        f_header_ << indent() << "  piprot_(::std::dynamic_pointer_cast<Protocol_>("
                   << "protocolFactory->getProtocol(itrans_)))," << endl << indent()
-                  << "  poprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>("
+                  << "  poprot_(::std::dynamic_pointer_cast<Protocol_>("
                   << "protocolFactory->getProtocol(otrans_))) {" << endl;
         // Throw a TException if either dynamic cast failed.
         f_header_ << indent() << "  if (!piprot_ || !poprot_) {" << endl << indent()
@@ -2371,7 +2376,7 @@
 
   if (style == "Cob") {
     f_header_ << indent()
-              << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl
+              << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl
               << indent() << "  return " << _this << "channel_;" << endl << indent() << "}" << endl;
     if (!gen_no_client_completion_) {
       f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl;
@@ -2423,11 +2428,11 @@
 
     if (style == "Cob") {
       f_header_ << indent()
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl
+                << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl
                 << indent()
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl
+                << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl
                 << indent()
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;"
+                << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;"
                 << endl;
     }
     f_header_ <<
@@ -2509,11 +2514,11 @@
     } else {
       if (!(*f_iter)->is_oneway()) {
         out << indent() << _this << "channel_->sendAndRecvMessage("
-            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());"
+            << "::std::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());"
             << endl;
       } else {
         out << indent() << _this << "channel_->sendMessage("
-            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get());" << endl;
+            << "::std::bind(cob, this), " << _this << "otrans_.get());" << endl;
       }
     }
     scope_down(out);
@@ -2828,8 +2833,8 @@
 
   t_cpp_generator* generator_;
   t_service* service_;
-  std::ofstream& f_header_;
-  std::ofstream& f_out_;
+  std::ostream& f_header_;
+  std::ostream& f_out_;
   string service_name_;
   string style_;
   string pstyle_;
@@ -2864,8 +2869,8 @@
     class_name_ = service_name_ + pstyle_ + "Processor";
     if_name_ = service_name_ + "CobSvIf";
 
-    finish_cob_ = "::apache::thrift::stdcxx::function<void(bool ok)> cob, ";
-    finish_cob_decl_ = "::apache::thrift::stdcxx::function<void(bool ok)>, ";
+    finish_cob_ = "::std::function<void(bool ok)> cob, ";
+    finish_cob_decl_ = "::std::function<void(bool ok)>, ";
     cob_arg_ = "cob, ";
     ret_type_ = "void ";
   } else {
@@ -2926,7 +2931,7 @@
   // Protected data members
   f_header_ << " protected:" << endl;
   indent_up();
-  f_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr<" << if_name_ << "> iface_;" << endl;
+  f_header_ << indent() << "::std::shared_ptr<" << if_name_ << "> iface_;" << endl;
   f_header_ << indent() << "virtual " << ret_type_ << "dispatchCall(" << finish_cob_
             << "::apache::thrift::protocol::TProtocol* iprot, "
             << "::apache::thrift::protocol::TProtocol* oprot, "
@@ -2982,29 +2987,29 @@
                             ? ""
                             : ", const " + type_name((*f_iter)->get_returntype()) + "& _return");
       f_header_ << indent() << "void return_" << (*f_iter)->get_name()
-                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                << "(::std::function<void(bool ok)> cob, int32_t seqid, "
                 << "::apache::thrift::protocol::TProtocol* oprot, "
                 << "void* ctx" << ret_arg << ");" << endl;
       if (generator_->gen_templates_) {
         f_header_ << indent() << "void return_" << (*f_iter)->get_name()
-                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                  << "(::std::function<void(bool ok)> cob, int32_t seqid, "
                   << "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl;
       }
       // XXX Don't declare throw if it doesn't exist
       f_header_ << indent() << "void throw_" << (*f_iter)->get_name()
-                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                << "(::std::function<void(bool ok)> cob, int32_t seqid, "
                 << "::apache::thrift::protocol::TProtocol* oprot, void* ctx, "
                 << "::apache::thrift::TDelayedException* _throw);" << endl;
       if (generator_->gen_templates_) {
         f_header_ << indent() << "void throw_" << (*f_iter)->get_name()
-                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                  << "(::std::function<void(bool ok)> cob, int32_t seqid, "
                   << "Protocol_* oprot, void* ctx, "
                   << "::apache::thrift::TDelayedException* _throw);" << endl;
       }
     }
   }
 
-  f_header_ << " public:" << endl << indent() << class_name_ << "(::apache::thrift::stdcxx::shared_ptr<" << if_name_
+  f_header_ << " public:" << endl << indent() << class_name_ << "(::std::shared_ptr<" << if_name_
             << "> iface) :" << endl;
   if (!extends_.empty()) {
     f_header_ << indent() << "  " << extends_ << "(iface)," << endl;
@@ -3142,14 +3147,14 @@
             << endl << " public:" << endl;
   indent_up();
 
-  f_header_ << indent() << factory_class_name_ << "(const ::apache::thrift::stdcxx::shared_ptr< " << if_factory_name
+  f_header_ << indent() << factory_class_name_ << "(const ::std::shared_ptr< " << if_factory_name
             << " >& handlerFactory) :" << endl << indent()
             << "    handlerFactory_(handlerFactory) {}" << endl << endl << indent()
-            << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+            << "::std::shared_ptr< ::apache::thrift::"
             << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
             << "getProcessor(const ::apache::thrift::TConnectionInfo& connInfo);" << endl;
 
-  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< "
+  f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr< "
             << if_factory_name << " > handlerFactory_;" << endl;
 
   indent_down();
@@ -3164,17 +3169,17 @@
   }
 
   // Generate the getProcessor() method
-  f_out_ << template_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+  f_out_ << template_header_ << indent() << "::std::shared_ptr< ::apache::thrift::"
          << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
          << factory_class_name_ << template_suffix_ << "::getProcessor("
          << "const ::apache::thrift::TConnectionInfo& connInfo) {" << endl;
   indent_up();
 
   f_out_ << indent() << "::apache::thrift::ReleaseHandler< " << if_factory_name
-         << " > cleanup(handlerFactory_);" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< "
+         << " > cleanup(handlerFactory_);" << endl << indent() << "::std::shared_ptr< "
          << if_name_ << " > handler("
          << "handlerFactory_->getHandler(connInfo), cleanup);" << endl << indent()
-         << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+         << "::std::shared_ptr< ::apache::thrift::"
          << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
          << "processor(new " << class_name_ << template_suffix_ << "(handler));" << endl << indent()
          << "return processor;" << endl;
@@ -3203,7 +3208,7 @@
     return;
   }
 
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
 
   t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
@@ -3250,7 +3255,7 @@
   vector<t_field*>::const_iterator x_iter;
   string service_func_name = "\"" + tservice->get_name() + "." + tfunction->get_name() + "\"";
 
-  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
 
   string prot_type = (specialized ? "Protocol_" : "::apache::thrift::protocol::TProtocol");
   string class_suffix;
@@ -3409,7 +3414,7 @@
       out << indent() << "template <class Protocol_>" << endl;
     }
     out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::process_"
-        << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+        << tfunction->get_name() << "(::std::function<void(bool ok)> cob, int32_t seqid, "
         << prot_type << "* iprot, " << prot_type << "* oprot)" << endl;
     scope_up(out);
 
@@ -3466,28 +3471,28 @@
       // No return.  Just hand off our cob.
       // TODO(dreiss): Call the cob immediately?
       out << indent() << "iface_->" << tfunction->get_name() << "("
-          << "::apache::thrift::stdcxx::bind(cob, true)" << endl;
+          << "::std::bind(cob, true)" << endl;
       indent_up();
       indent_up();
     } else {
       string ret_arg, ret_placeholder;
       if (!tfunction->get_returntype()->is_void()) {
         ret_arg = ", const " + type_name(tfunction->get_returntype()) + "& _return";
-        ret_placeholder = ", ::apache::thrift::stdcxx::placeholders::_1";
+        ret_placeholder = ", ::std::placeholders::_1";
       }
 
       // When gen_templates_ is true, the return_ and throw_ functions are
       // overloaded.  We have to declare pointers to them so that the compiler
       // can resolve the correct overloaded version.
       out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix
-          << "::*return_fn)(::apache::thrift::stdcxx::function<void(bool ok)> "
+          << "::*return_fn)(::std::function<void(bool ok)> "
           << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg
           << ") =" << endl;
       out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix
           << "::return_" << tfunction->get_name() << ";" << endl;
       if (!xceptions.empty()) {
         out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix
-            << "::*throw_fn)(::apache::thrift::stdcxx::function<void(bool ok)> "
+            << "::*throw_fn)(::std::function<void(bool ok)> "
             << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, "
             << "::apache::thrift::TDelayedException* _throw) =" << endl;
         out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix
@@ -3497,11 +3502,11 @@
       out << indent() << "iface_->" << tfunction->get_name() << "(" << endl;
       indent_up();
       indent_up();
-      out << indent() << "::apache::thrift::stdcxx::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder
+      out << indent() << "::std::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder
           << ")";
       if (!xceptions.empty()) {
-        out << ',' << endl << indent() << "::apache::thrift::stdcxx::bind(throw_fn, this, cob, seqid, oprot, "
-            << "ctx, ::apache::thrift::stdcxx::placeholders::_1)";
+        out << ',' << endl << indent() << "::std::bind(throw_fn, this, cob, seqid, oprot, "
+            << "ctx, ::std::placeholders::_1)";
       }
     }
 
@@ -3526,7 +3531,7 @@
         out << indent() << "template <class Protocol_>" << endl;
       }
       out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_"
-          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+          << tfunction->get_name() << "(::std::function<void(bool ok)> cob, int32_t seqid, "
           << prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl;
       scope_up(out);
 
@@ -3574,7 +3579,7 @@
         out << indent() << "template <class Protocol_>" << endl;
       }
       out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_"
-          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+          << tfunction->get_name() << "(::std::function<void(bool ok)> cob, int32_t seqid, "
           << prot_type << "* oprot, void* ctx, "
           << "::apache::thrift::TDelayedException* _throw)" << endl;
       scope_up(out);
@@ -3662,7 +3667,7 @@
 
   string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
 
-  ofstream f_skeleton;
+  ofstream_with_content_based_conditional_update f_skeleton;
   f_skeleton.open(f_skeleton_name.c_str());
   f_skeleton << "// This autogenerated skeleton file illustrates how to build a server." << endl
              << "// You should copy it to another filename to avoid overwriting it." << endl << endl
@@ -3704,13 +3709,13 @@
   f_skeleton << indent() << "int main(int argc, char **argv) {" << endl;
   indent_up();
   f_skeleton
-      << indent() << "int port = 9090;" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << svcname
+      << indent() << "int port = 9090;" << endl << indent() << "::std::shared_ptr<" << svcname
       << "Handler> handler(new " << svcname << "Handler());" << endl << indent()
-      << "::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl
-      << indent() << "::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));"
+      << "::std::shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl
+      << indent() << "::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));"
       << endl << indent()
-      << "::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl
-      << indent() << "::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());"
+      << "::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl
+      << indent() << "::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());"
       << endl << endl << indent()
       << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);"
       << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl;
@@ -3724,7 +3729,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_cpp_generator::generate_deserialize_field(ofstream& out,
+void t_cpp_generator::generate_deserialize_field(ostream& out,
                                                  t_field* tfield,
                                                  string prefix,
                                                  string suffix) {
@@ -3793,13 +3798,13 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_cpp_generator::generate_deserialize_struct(ofstream& out,
+void t_cpp_generator::generate_deserialize_struct(ostream& out,
                                                   t_struct* tstruct,
                                                   string prefix,
                                                   bool pointer) {
   if (pointer) {
     indent(out) << "if (!" << prefix << ") { " << endl;
-    indent(out) << "  " << prefix << " = ::apache::thrift::stdcxx::shared_ptr<" << type_name(tstruct) << ">(new "
+    indent(out) << "  " << prefix << " = ::std::shared_ptr<" << type_name(tstruct) << ">(new "
                 << type_name(tstruct) << ");" << endl;
     indent(out) << "}" << endl;
     indent(out) << "xfer += " << prefix << "->read(iprot);" << endl;
@@ -3817,7 +3822,7 @@
   }
 }
 
-void t_cpp_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_cpp_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   string size = tmp("_size");
@@ -3878,7 +3883,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_cpp_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_cpp_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
@@ -3893,7 +3898,7 @@
   generate_deserialize_field(out, &fval);
 }
 
-void t_cpp_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_cpp_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -3904,7 +3909,7 @@
   indent(out) << prefix << ".insert(" << elem << ");" << endl;
 }
 
-void t_cpp_generator::generate_deserialize_list_element(ofstream& out,
+void t_cpp_generator::generate_deserialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string prefix,
                                                         bool use_push,
@@ -3927,7 +3932,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_cpp_generator::generate_serialize_field(ofstream& out,
+void t_cpp_generator::generate_serialize_field(ostream& out,
                                                t_field* tfield,
                                                string prefix,
                                                string suffix) {
@@ -4000,7 +4005,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_cpp_generator::generate_serialize_struct(ofstream& out,
+void t_cpp_generator::generate_serialize_struct(ostream& out,
                                                 t_struct* tstruct,
                                                 string prefix,
                                                 bool pointer) {
@@ -4017,7 +4022,7 @@
   }
 }
 
-void t_cpp_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_cpp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -4063,7 +4068,7 @@
  * Serializes the members of a map.
  *
  */
-void t_cpp_generator::generate_serialize_map_element(ofstream& out, t_map* tmap, string iter) {
+void t_cpp_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter) {
   t_field kfield(tmap->get_key_type(), iter + "->first");
   generate_serialize_field(out, &kfield, "");
 
@@ -4074,7 +4079,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_cpp_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_cpp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), "(*" + iter + ")");
   generate_serialize_field(out, &efield, "");
 }
@@ -4082,7 +4087,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_cpp_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_cpp_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), "(*" + iter + ")");
   generate_serialize_field(out, &efield, "");
 }
@@ -4291,7 +4296,7 @@
   }
   result += type_name(tfield->get_type());
   if (is_reference(tfield)) {
-    result = "::apache::thrift::stdcxx::shared_ptr<" + result + ">";
+    result = "::std::shared_ptr<" + result + ">";
   }
   if (pointer) {
     result += "*";
@@ -4370,13 +4375,13 @@
       cob_type = (ttype->is_void() ? "()" : ("(" + type_name(ttype) + " const& _return)"));
       if (has_xceptions) {
         exn_cob
-            = ", ::apache::thrift::stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */";
+            = ", ::std::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */";
       }
     } else {
       throw "UNKNOWN STYLE";
     }
 
-    return "void " + prefix + tfunction->get_name() + "(::apache::thrift::stdcxx::function<void" + cob_type + "> cob"
+    return "void " + prefix + tfunction->get_name() + "(::std::function<void" + cob_type + "> cob"
            + exn_cob + argument_list(arglist, name_params, true) + ")";
   } else {
     throw "UNKNOWN STYLE";
diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
index a6cb09d..9d1e29e 100644
--- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc
@@ -37,7 +37,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -100,46 +100,46 @@
   void generate_union(t_struct* tunion);
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
-  void generate_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset);
-  void generate_csharp_property(ofstream& out,
+  void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset);
+  void generate_csharp_property(ostream& out,
                                 t_field* tfield,
                                 bool isPublic,
                                 bool includeIsset = true,
                                 std::string fieldPrefix = "");
-  bool print_const_value(std::ofstream& out,
+  bool print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false,
                          bool needtype = false);
-  std::string render_const_value(std::ofstream& out,
+  std::string render_const_value(std::ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
-  void print_const_constructor(std::ofstream& out, std::vector<t_const*> consts);
-  void print_const_def_value(std::ofstream& out,
+  void print_const_constructor(std::ostream& out, std::vector<t_const*> consts);
+  void print_const_def_value(std::ostream& out,
                              std::string name,
                              t_type* type,
                              t_const_value* value);
 
   void generate_csharp_struct(t_struct* tstruct, bool is_exception);
   void generate_csharp_union(t_struct* tunion);
-  void generate_csharp_struct_definition(std::ofstream& out,
+  void generate_csharp_struct_definition(std::ostream& out,
                                          t_struct* tstruct,
                                          bool is_xception = false,
                                          bool in_class = false,
                                          bool is_result = false);
-  void generate_csharp_union_definition(std::ofstream& out, t_struct* tunion);
-  void generate_csharp_union_class(std::ofstream& out, t_struct* tunion, t_field* tfield);
-  void generate_csharp_wcffault(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_equals(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_struct_hashcode(std::ofstream& out, t_struct* tstruct);
-  void generate_csharp_union_reader(std::ofstream& out, t_struct* tunion);
+  void generate_csharp_union_definition(std::ostream& out, t_struct* tunion);
+  void generate_csharp_union_class(std::ostream& out, t_struct* tunion, t_field* tfield);
+  void generate_csharp_wcffault(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_tostring(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_equals(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_hashcode(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_union_reader(std::ostream& out, t_struct* tunion);
 
   void generate_function_helpers(t_function* tfunction);
   void generate_service_interface(t_service* tservice);
@@ -156,36 +156,36 @@
   void generate_process_function(t_service* tservice, t_function* function);
   void generate_process_function_async(t_service* tservice, t_function* function);
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   bool is_propertyless = false);
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-  void generate_deserialize_list_element(std::ofstream& out, t_list* list, std::string prefix = "");
-  void generate_serialize_field(std::ofstream& out,
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_list_element(std::ostream& out, t_list* list, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out,
                                 t_field* tfield,
                                 std::string prefix = "",
                                 bool is_element = false,
                                 bool is_propertyless = false);
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_csharp_doc(std::ofstream& out, t_field* field);
-  void generate_csharp_doc(std::ofstream& out, t_doc* tdoc);
-  void generate_csharp_doc(std::ofstream& out, t_function* tdoc);
-  void generate_csharp_docstring_comment(std::ofstream& out, string contents);
+  void generate_csharp_doc(std::ostream& out, t_field* field);
+  void generate_csharp_doc(std::ostream& out, t_doc* tdoc);
+  void generate_csharp_doc(std::ostream& out, t_function* tdoc);
+  void generate_csharp_docstring_comment(std::ostream& out, string contents);
 
-  void start_csharp_namespace(std::ofstream& out);
-  void end_csharp_namespace(std::ofstream& out);
+  void start_csharp_namespace(std::ostream& out);
+  void end_csharp_namespace(std::ostream& out);
 
   std::string csharp_type_usings();
   std::string csharp_thrift_usings();
@@ -224,7 +224,7 @@
 
 private:
   std::string namespace_name_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
   std::string namespace_dir_;
   bool async_;
   bool nullable_;
@@ -403,14 +403,14 @@
   csharp_keywords["yield"] = 1;
 }
 
-void t_csharp_generator::start_csharp_namespace(ofstream& out) {
+void t_csharp_generator::start_csharp_namespace(ostream& out) {
   if (!namespace_name_.empty()) {
     out << "namespace " << namespace_name_ << "\n";
     scope_up(out);
   }
 }
 
-void t_csharp_generator::end_csharp_namespace(ofstream& out) {
+void t_csharp_generator::end_csharp_namespace(ostream& out) {
   if (!namespace_name_.empty()) {
     scope_down(out);
   }
@@ -422,7 +422,7 @@
          + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n"
          + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "")
          + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "")
-         + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "")
+         + ((serialize_ || wcf_) ? "#endif\n" : "")
          + "using System.Runtime.Serialization;\n";
 }
 
@@ -438,7 +438,7 @@
 
 void t_csharp_generator::generate_enum(t_enum* tenum) {
   string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs";
-  ofstream f_enum;
+  ofstream_with_content_based_conditional_update f_enum;
   f_enum.open(f_enum_name.c_str());
 
   f_enum << autogen_comment() << endl;
@@ -471,7 +471,7 @@
     return;
   }
   string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs";
-  ofstream f_consts;
+  ofstream_with_content_based_conditional_update f_consts;
   f_consts.open(f_consts_name.c_str());
 
   f_consts << autogen_comment() << csharp_type_usings() << endl;
@@ -504,15 +504,15 @@
   f_consts.close();
 }
 
-void t_csharp_generator::print_const_def_value(std::ofstream& out,
+void t_csharp_generator::print_const_def_value(std::ostream& out,
                                                string name,
                                                t_type* type,
                                                t_const_value* value) {
   if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     prepare_member_name_mapping((t_struct*)type);
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_field* field = NULL;
@@ -532,8 +532,8 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
       string val = render_const_value(out, name, vtype, v_iter->second);
@@ -557,7 +557,7 @@
   }
 }
 
-void t_csharp_generator::print_const_constructor(std::ofstream& out, std::vector<t_const*> consts) {
+void t_csharp_generator::print_const_constructor(std::ostream& out, std::vector<t_const*> consts) {
   indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()"
               << endl;
   scope_up(out);
@@ -574,7 +574,7 @@
 
 // it seems like all that methods that call this are using in_static to be the opposite of what it
 // would imply
-bool t_csharp_generator::print_const_value(std::ofstream& out,
+bool t_csharp_generator::print_const_value(std::ostream& out,
                                            string name,
                                            t_type* type,
                                            t_const_value* value,
@@ -614,7 +614,7 @@
   return need_static_construction;
 }
 
-std::string t_csharp_generator::render_const_value(ofstream& out,
+std::string t_csharp_generator::render_const_value(ostream& out,
                                                    string name,
                                                    t_type* type,
                                                    t_const_value* value) {
@@ -671,7 +671,7 @@
 
 void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) {
   string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
 
   f_struct.open(f_struct_name.c_str());
 
@@ -682,7 +682,7 @@
   f_struct.close();
 }
 
-void t_csharp_generator::generate_csharp_struct_definition(ofstream& out,
+void t_csharp_generator::generate_csharp_struct_definition(ostream& out,
                                                            t_struct* tstruct,
                                                            bool is_exception,
                                                            bool in_class,
@@ -843,7 +843,7 @@
         } else {
           out << ", ";
         }
-        out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name();
+        out << type_name((*m_iter)->get_type()) << " " << normalize_name((*m_iter)->get_name());
       }
     }
     out << ") : this() {" << endl;
@@ -851,7 +851,7 @@
 
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if (field_is_required((*m_iter))) {
-        indent(out) << "this." << prop_name((*m_iter)) << " = " << (*m_iter)->get_name() << ";"
+        indent(out) << "this." << prop_name((*m_iter)) << " = " << normalize_name((*m_iter)->get_name()) << ";"
                     << endl;
       }
     }
@@ -885,7 +885,7 @@
   }
 }
 
-void t_csharp_generator::generate_csharp_wcffault(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_wcffault(ostream& out, t_struct* tstruct) {
   out << endl;
   indent(out) << "#if !SILVERLIGHT" << endl;
   indent(out) << "[Serializable]" << endl;
@@ -903,7 +903,10 @@
 
   // make private members with public Properties
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+    // if the field is requied, then we use auto-properties
+    if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) {
+      indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+    }
   }
   out << endl;
 
@@ -915,7 +918,7 @@
   out << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_reader(ostream& out, t_struct* tstruct) {
   indent(out) << "public void Read (TProtocol iprot)" << endl;
   scope_up(out);
 
@@ -988,7 +991,7 @@
       indent_up();
       out << indent()
           << "throw new TProtocolException(TProtocolException.INVALID_DATA, "
-          << "\"required field " << prop_name((*f_iter)) << " not set\");" 
+          << "\"required field " << prop_name((*f_iter)) << " not set\");"
           << endl;
       indent_down();
     }
@@ -1005,7 +1008,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public void Write(TProtocol oprot) {" << endl;
   indent_up();
 
@@ -1084,7 +1087,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_result_writer(ostream& out, t_struct* tstruct) {
   indent(out) << "public void Write(TProtocol oprot) {" << endl;
   indent_up();
 
@@ -1156,7 +1159,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_tostring(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_tostring(ostream& out, t_struct* tstruct) {
   indent(out) << "public override string ToString() {" << endl;
   indent_up();
 
@@ -1230,7 +1233,7 @@
 
 void t_csharp_generator::generate_csharp_union(t_struct* tunion) {
   string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs";
-  ofstream f_union;
+  ofstream_with_content_based_conditional_update f_union;
 
   f_union.open(f_union_name.c_str());
 
@@ -1241,7 +1244,7 @@
   f_union.close();
 }
 
-void t_csharp_generator::generate_csharp_union_definition(std::ofstream& out, t_struct* tunion) {
+void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_struct* tunion) {
   // Let's define the class first
   start_csharp_namespace(out);
 
@@ -1292,7 +1295,7 @@
   end_csharp_namespace(out);
 }
 
-void t_csharp_generator::generate_csharp_union_class(std::ofstream& out,
+void t_csharp_generator::generate_csharp_union_class(std::ostream& out,
                                                      t_struct* tunion,
                                                      t_field* tfield) {
   indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {"
@@ -1341,7 +1344,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_equals(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_equals(ostream& out, t_struct* tstruct) {
   indent(out) << "public override bool Equals(object that) {" << endl;
   indent_up();
 
@@ -1390,7 +1393,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_csharp_struct_hashcode(ofstream& out, t_struct* tstruct) {
+void t_csharp_generator::generate_csharp_struct_hashcode(ostream& out, t_struct* tstruct) {
   indent(out) << "public override int GetHashCode() {" << endl;
   indent_up();
 
@@ -1475,7 +1478,7 @@
   generate_csharp_doc(f_service_, tservice);
 
   if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+    indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
   }
   indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl;
 
@@ -1487,12 +1490,12 @@
 
     // if we're using WCF, add the corresponding attributes
     if (wcf_) {
-      indent(f_service_) << "[OperationContract]" << endl;
+      indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl;
 
       const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
       vector<t_field*>::const_iterator x_iter;
       for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent(f_service_) << "[FaultContract(typeof("
+        indent(f_service_) << "[System.ServiceModel.FaultContract(typeof("
           + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
       }
     }
@@ -1514,7 +1517,7 @@
   generate_csharp_doc(f_service_, tservice);
 
   if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+    indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
   }
   indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl;
 
@@ -1526,12 +1529,12 @@
 
     // if we're using WCF, add the corresponding attributes
     if (wcf_) {
-      indent(f_service_) << "[OperationContract]" << endl;
+      indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl;
 
       const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
       vector<t_field*>::const_iterator x_iter;
       for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-        indent(f_service_) << "[FaultContract(typeof("
+        indent(f_service_) << "[System.ServiceModel.FaultContract(typeof("
           + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
       }
     }
@@ -1552,7 +1555,7 @@
   generate_csharp_doc(f_service_, tservice);
 
   if (wcf_) {
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+    indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
   }
 
   indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl;
@@ -1690,6 +1693,7 @@
 
     if (!async_) {
       indent(f_service_) << "#if SILVERLIGHT" << endl;
+      indent(f_service_) << endl;
     }
     // Begin_
     indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl;
@@ -1766,51 +1770,52 @@
       indent(f_service_) << "#endif" << endl << endl;
     }
 
-    // "Normal" Synchronous invoke
     generate_csharp_doc(f_service_, *f_iter);
     indent(f_service_) << "public " << function_signature(*f_iter) << endl;
     scope_up(f_service_);
 
+    // silverlight invoke
     if (!async_) {
-      indent(f_service_) << "#if !SILVERLIGHT" << endl;
-      indent(f_service_) << "send_" << funname << "(";
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
 
-      first = true;
+      indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null";
       for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-        if (first) {
-          first = false;
-        } else {
-          f_service_ << ", ";
-        }
-        f_service_ << normalize_name((*fld_iter)->get_name());
+        f_service_ << ", " << normalize_name((*fld_iter)->get_name());
       }
       f_service_ << ");" << endl;
-
+      
       if (!(*f_iter)->is_oneway()) {
         f_service_ << indent();
         if (!(*f_iter)->get_returntype()->is_void()) {
           f_service_ << "return ";
         }
-        f_service_ << "recv_" << funname << "();" << endl;
+        f_service_ << "End_" << funname << "(asyncResult);" << endl;
       }
       f_service_ << endl;
 
       indent(f_service_) << "#else" << endl;
     }
 
-    // Silverlight synchronous invoke
-    indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null";
+    // synchronous invoke
+    indent(f_service_) << "send_" << funname << "(";
+  
+    first = true;
     for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      f_service_ << ", " << normalize_name((*fld_iter)->get_name());
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << normalize_name((*fld_iter)->get_name());
     }
     f_service_ << ");" << endl;
-
+  
     if (!(*f_iter)->is_oneway()) {
       f_service_ << indent();
       if (!(*f_iter)->get_returntype()->is_void()) {
         f_service_ << "return ";
       }
-      f_service_ << "End_" << funname << "(asyncResult);" << endl;
+      f_service_ << "recv_" << funname << "();" << endl;
     }
     f_service_ << endl;
 
@@ -1829,12 +1834,8 @@
     if (!async_) {
       indent(f_service_) << "#if SILVERLIGHT" << endl;
     }
+
     indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl;
-    if (!async_) {
-      indent(f_service_) << "#else" << endl;
-      indent(f_service_) << "public " << function_signature(&send_function) << endl;
-      indent(f_service_) << "#endif" << endl;
-    }
     scope_up(f_service_);
 
     f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", "
@@ -1849,20 +1850,40 @@
 
     f_service_ << indent() << "args.Write(oprot_);" << endl << indent()
                << "oprot_.WriteMessageEnd();" << endl;
-    ;
+    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl;
+      
+    scope_down(f_service_);
+    f_service_ << endl;
 
     if (!async_) {
-      indent(f_service_) << "#if SILVERLIGHT" << endl;
-    }
-    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl;
-    if (!async_) {
       indent(f_service_) << "#else" << endl;
-      indent(f_service_) << "oprot_.Transport.Flush();" << endl;
+      f_service_ << endl;
+    }
+
+    indent(f_service_) << "public " << function_signature(&send_function) << endl;
+    scope_up(f_service_);
+
+    f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call")
+               << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname
+               << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << prop_name(*fld_iter) << " = "
+                 << normalize_name((*fld_iter)->get_name()) << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.Write(oprot_);" << endl << indent()
+               << "oprot_.WriteMessageEnd();" << endl;
+
+    indent(f_service_) << "oprot_.Transport.Flush();" << endl;
+    cleanup_member_name_mapping(arg_struct);
+    scope_down(f_service_);
+
+    if (!async_) {
       indent(f_service_) << "#endif" << endl;
     }
 
-    cleanup_member_name_mapping(arg_struct);
-    scope_down(f_service_);
     f_service_ << endl;
 
     if (!(*f_iter)->is_oneway()) {
@@ -2049,7 +2070,7 @@
   string extends_processor = "";
   if (tservice->get_extends() != NULL) {
     extends = type_name(tservice->get_extends());
-    extends_processor = extends + ".Processor, ";
+    extends_processor = extends + ".AsyncProcessor, ";
   }
 
   indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl;
@@ -2378,7 +2399,7 @@
   f_service_ << endl;
 }
 
-void t_csharp_generator::generate_csharp_union_reader(std::ofstream& out, t_struct* tunion) {
+void t_csharp_generator::generate_csharp_union_reader(std::ostream& out, t_struct* tunion) {
   // Thanks to THRIFT-1768, we don't need to check for required fields in the union
   const vector<t_field*>& fields = tunion->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -2452,7 +2473,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_csharp_generator::generate_deserialize_field(ofstream& out,
+void t_csharp_generator::generate_deserialize_field(ostream& out,
                                                     t_field* tfield,
                                                     string prefix,
                                                     bool is_propertyless) {
@@ -2525,7 +2546,7 @@
   }
 }
 
-void t_csharp_generator::generate_deserialize_struct(ofstream& out,
+void t_csharp_generator::generate_deserialize_struct(ostream& out,
                                                      t_struct* tstruct,
                                                      string prefix) {
   if (union_ && tstruct->is_union()) {
@@ -2536,7 +2557,7 @@
   }
 }
 
-void t_csharp_generator::generate_deserialize_container(ofstream& out,
+void t_csharp_generator::generate_deserialize_container(ostream& out,
                                                         t_type* ttype,
                                                         string prefix) {
   scope_up(out);
@@ -2587,7 +2608,7 @@
   scope_down(out);
 }
 
-void t_csharp_generator::generate_deserialize_map_element(ofstream& out,
+void t_csharp_generator::generate_deserialize_map_element(ostream& out,
                                                           t_map* tmap,
                                                           string prefix) {
   string key = tmp("_key");
@@ -2605,7 +2626,7 @@
   indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
 }
 
-void t_csharp_generator::generate_deserialize_set_element(ofstream& out,
+void t_csharp_generator::generate_deserialize_set_element(ostream& out,
                                                           t_set* tset,
                                                           string prefix) {
   string elem = tmp("_elem");
@@ -2618,7 +2639,7 @@
   indent(out) << prefix << ".Add(" << elem << ");" << endl;
 }
 
-void t_csharp_generator::generate_deserialize_list_element(ofstream& out,
+void t_csharp_generator::generate_deserialize_list_element(ostream& out,
                                                            t_list* tlist,
                                                            string prefix) {
   string elem = tmp("_elem");
@@ -2631,7 +2652,7 @@
   indent(out) << prefix << ".Add(" << elem << ");" << endl;
 }
 
-void t_csharp_generator::generate_serialize_field(ofstream& out,
+void t_csharp_generator::generate_serialize_field(ostream& out,
                                                   t_field* tfield,
                                                   string prefix,
                                                   bool is_element,
@@ -2704,14 +2725,14 @@
   }
 }
 
-void t_csharp_generator::generate_serialize_struct(ofstream& out,
+void t_csharp_generator::generate_serialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix) {
   (void)tstruct;
   out << indent() << prefix << ".Write(oprot);" << endl;
 }
 
-void t_csharp_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_csharp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -2763,7 +2784,7 @@
   scope_down(out);
 }
 
-void t_csharp_generator::generate_serialize_map_element(ofstream& out,
+void t_csharp_generator::generate_serialize_map_element(ostream& out,
                                                         t_map* tmap,
                                                         string iter,
                                                         string map) {
@@ -2773,25 +2794,25 @@
   generate_serialize_field(out, &vfield, "", true);
 }
 
-void t_csharp_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_csharp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "", true);
 }
 
-void t_csharp_generator::generate_serialize_list_element(ofstream& out,
+void t_csharp_generator::generate_serialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "", true);
 }
 
-void t_csharp_generator::generate_property(ofstream& out,
+void t_csharp_generator::generate_property(ostream& out,
                                            t_field* tfield,
                                            bool isPublic,
                                            bool generateIsset) {
   generate_csharp_property(out, tfield, isPublic, generateIsset, "_");
 }
-void t_csharp_generator::generate_csharp_property(ofstream& out,
+void t_csharp_generator::generate_csharp_property(ostream& out,
                                                   t_field* tfield,
                                                   bool isPublic,
                                                   bool generateIsset,
@@ -3040,7 +3061,7 @@
       ttype = ((t_typedef*)ttype)->get_type();
     }
     if (ttype->is_base_type() && field_has_default(tfield)) {
-      ofstream dummy;
+      std::ofstream dummy;
       result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -3158,11 +3179,11 @@
   throw "INVALID TYPE IN type_to_enum: " + type->get_name();
 }
 
-void t_csharp_generator::generate_csharp_docstring_comment(ofstream& out, string contents) {
+void t_csharp_generator::generate_csharp_docstring_comment(ostream& out, string contents) {
   generate_docstring_comment(out, "/// <summary>\n", "/// ", contents, "/// </summary>\n");
 }
 
-void t_csharp_generator::generate_csharp_doc(ofstream& out, t_field* field) {
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_field* field) {
   if (field->get_type()->is_enum()) {
     string combined_message = field->get_doc() + "\n<seealso cref=\""
                               + get_enum_class_name(field->get_type()) + "\"/>";
@@ -3172,13 +3193,13 @@
   }
 }
 
-void t_csharp_generator::generate_csharp_doc(ofstream& out, t_doc* tdoc) {
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_csharp_docstring_comment(out, tdoc->get_doc());
   }
 }
 
-void t_csharp_generator::generate_csharp_doc(ofstream& out, t_function* tfunction) {
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_function* tfunction) {
   if (tfunction->has_doc()) {
     stringstream ps;
     const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc
index 35f611d..df56cfc 100644
--- a/compiler/cpp/src/thrift/generate/t_d_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc
@@ -118,7 +118,7 @@
   virtual void generate_consts(std::vector<t_const*> consts) {
     if (!consts.empty()) {
       string f_consts_name = package_dir_ + program_name_ + "_constants.d";
-      ofstream f_consts;
+      ofstream_with_content_based_conditional_update f_consts;
       f_consts.open(f_consts_name.c_str());
 
       f_consts << autogen_comment() << "module " << render_package(*program_) << program_name_
@@ -201,7 +201,7 @@
 
     // Service implementation file includes
     string f_servicename = package_dir_ + svc_name + ".d";
-    std::ofstream f_service;
+    ofstream_with_content_based_conditional_update f_service;
     f_service.open(f_servicename.c_str());
     f_service << autogen_comment() << "module " << render_package(*program_) << svc_name << ";"
               << endl << endl;
@@ -339,13 +339,13 @@
 
     // Server skeleton generation.
     string f_skeletonname = package_dir_ + svc_name + "_server.skeleton.d";
-    std::ofstream f_skeleton;
+    ofstream_with_content_based_conditional_update f_skeleton;
     f_skeleton.open(f_skeletonname.c_str());
     print_server_skeleton(f_skeleton, tservice);
     f_skeleton.close();
   }
 
-  void emit_doc(t_doc *doc, std::ofstream& out) {
+  void emit_doc(t_doc *doc, std::ostream& out) {
     if (!doc->has_doc()) {
       return;
     }
@@ -557,8 +557,8 @@
 
         const vector<t_field*>& fields = ((t_struct*)type)->get_members();
         vector<t_field*>::const_iterator f_iter;
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+        map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
         for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
           t_type* field_type = NULL;
           for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -576,8 +576,8 @@
       } else if (type->is_map()) {
         t_type* ktype = ((t_map*)type)->get_key_type();
         t_type* vtype = ((t_map*)type)->get_val_type();
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+        map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
         for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
           string key = render_const_value(ktype, v_iter->first);
           string val = render_const_value(vtype, v_iter->second);
@@ -733,8 +733,8 @@
    * File streams, stored here to avoid passing them as parameters to every
    * function.
    */
-  ofstream f_types_;
-  ofstream f_header_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_header_;
 
   string package_dir_;
 };
diff --git a/compiler/cpp/src/thrift/generate/t_dart_generator.cc b/compiler/cpp/src/thrift/generate/t_dart_generator.cc
index f7bd1c2..414c333 100644
--- a/compiler/cpp/src/thrift/generate/t_dart_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_dart_generator.cc
@@ -31,7 +31,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -141,13 +141,13 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false);
-  std::string render_const_value(ofstream& out,
+  std::string render_const_value(ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
@@ -158,21 +158,21 @@
 
   void generate_dart_struct(t_struct* tstruct, bool is_exception);
 
-  void generate_dart_struct_definition(std::ofstream& out,
+  void generate_dart_struct_definition(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false,
                                        bool is_result = false,
                                        string export_file_name = "");
-  void generate_dart_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_struct_tostring(std::ofstream& out, t_struct* tstruct);
+  void generate_dart_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_dart_validator(std::ostream& out, t_struct* tstruct);
+  void generate_dart_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_dart_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_dart_struct_tostring(std::ostream& out, t_struct* tstruct);
   std::string get_dart_type_string(t_type* type);
-  void generate_generic_field_getters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_field_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_dart_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_field_getters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_field_setters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct);
+  void generate_dart_bean_boilerplate(std::ostream& out, t_struct* tstruct);
 
   void generate_function_helpers(t_function* tfunction);
   std::string init_value(t_field* tfield);
@@ -184,7 +184,7 @@
   std::string get_constants_class_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
+  void generate_isset_set(ostream& out, t_field* field);
 
   void generate_service_interface(t_service* tservice);
   void generate_service_helpers(t_service* tservice);
@@ -196,38 +196,38 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_dart_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_dart_doc(std::ostream& out, t_doc* tdoc);
 
-  void generate_dart_doc(std::ofstream& out, t_function* tdoc);
+  void generate_dart_doc(std::ostream& out, t_function* tdoc);
 
   /**
    * Helper rendering functions
@@ -265,7 +265,7 @@
   std::string constant_name(std::string name);
 
 private:
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
 
   std::string library_name_;
   std::string library_prefix_;
@@ -391,7 +391,7 @@
     f_library_name = get_out_dir() + "/" + library_name_ + ".dart";
   }
 
-  ofstream f_library;
+  ofstream_with_content_based_conditional_update f_library;
   f_library.open(f_library_name.c_str());
 
   f_library << autogen_comment() << endl;
@@ -413,7 +413,7 @@
 
 void t_dart_generator::generate_dart_pubspec() {
   string f_pubspec_name = base_dir_ + "/pubspec.yaml";
-  ofstream f_pubspec;
+  ofstream_with_content_based_conditional_update f_pubspec;
   f_pubspec.open(f_pubspec_name.c_str());
 
   indent(f_pubspec) << "name: " << library_name_ << endl;
@@ -478,7 +478,7 @@
   string file_name = get_file_name(tenum->get_name());
 
   string f_enum_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_enum;
+  ofstream_with_content_based_conditional_update f_enum;
   f_enum.open(f_enum_name.c_str());
 
   // Comment and add library
@@ -540,7 +540,7 @@
   string file_name = get_file_name(class_name);
 
   string f_consts_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_consts;
+  ofstream_with_content_based_conditional_update f_consts;
   f_consts.open(f_consts_name.c_str());
 
   // Print header
@@ -566,7 +566,7 @@
   f_consts.close();
 }
 
-void t_dart_generator::print_const_value(std::ofstream& out,
+void t_dart_generator::print_const_value(std::ostream& out,
                                         string name,
                                         t_type* type,
                                         t_const_value* value,
@@ -594,8 +594,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     out << type_name(type) << " " << name << " = new " << type_name(type) << "()";
     indent_up();
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
@@ -623,8 +623,8 @@
 
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
@@ -668,7 +668,7 @@
   }
 }
 
-string t_dart_generator::render_const_value(ofstream& out,
+string t_dart_generator::render_const_value(ostream& out,
                                            string name,
                                            t_type* type,
                                            t_const_value* value) {
@@ -740,7 +740,7 @@
 void t_dart_generator::generate_dart_struct(t_struct* tstruct, bool is_exception) {
   string file_name = get_file_name(tstruct->get_name());
   string f_struct_name = src_dir_ + "/" + file_name + ".dart";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << dart_library(file_name) << endl;
@@ -764,7 +764,7 @@
  * @param in_class     If inside a class, needs to be static class
  * @param is_result    If this is a result it needs a different writer
  */
-void t_dart_generator::generate_dart_struct_definition(ofstream& out,
+void t_dart_generator::generate_dart_struct_definition(ostream& out,
                                                        t_struct* tstruct,
                                                        bool is_exception,
                                                        bool is_result,
@@ -777,10 +777,10 @@
   }
   indent(out) << "class " << class_name << " ";
 
-  if (is_exception) {
-    out << "extends Error ";
-  }
   out << "implements TBase";
+  if (is_exception) {
+    out << ", Exception ";
+  }
   scope_up(out);
 
   indent(out) << "static final TStruct _STRUCT_DESC = new TStruct(\"" << class_name
@@ -861,7 +861,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_dart_generator::generate_dart_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_dart_generator::generate_dart_struct_reader(ostream& out, t_struct* tstruct) {
   indent(out) << "read(TProtocol iprot)";
   scope_up(out);
 
@@ -949,7 +949,7 @@
 
 // generates dart method to perform various checks
 // (e.g. check that all required fields are set)
-void t_dart_generator::generate_dart_validator(ofstream& out, t_struct* tstruct) {
+void t_dart_generator::generate_dart_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "validate()";
   scope_up(out);
 
@@ -1000,7 +1000,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_dart_generator::generate_dart_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_dart_generator::generate_dart_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "write(TProtocol oprot)";
   scope_up(out);
 
@@ -1056,7 +1056,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_dart_generator::generate_dart_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_dart_generator::generate_dart_struct_result_writer(ostream& out, t_struct* tstruct) {
   indent(out) << "write(TProtocol oprot)";
   scope_up(out);
 
@@ -1097,7 +1097,7 @@
   scope_down(out, endl2);
 }
 
-void t_dart_generator::generate_generic_field_getters(std::ofstream& out,
+void t_dart_generator::generate_generic_field_getters(std::ostream& out,
                                                       t_struct* tstruct) {
   // create the getter
   indent(out) << "getFieldValue(int fieldID)";
@@ -1127,7 +1127,7 @@
   scope_down(out, endl2);  // method
 }
 
-void t_dart_generator::generate_generic_field_setters(std::ofstream& out,
+void t_dart_generator::generate_generic_field_setters(std::ostream& out,
                                                       t_struct* tstruct) {
 
   // create the setter
@@ -1172,7 +1172,7 @@
 }
 
 // Creates a generic isSet method that takes the field number as argument
-void t_dart_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+void t_dart_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -1208,7 +1208,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_dart_generator::generate_dart_bean_boilerplate(ofstream& out,
+void t_dart_generator::generate_dart_bean_boilerplate(ostream& out,
                                                     t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -1257,7 +1257,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_dart_generator::generate_dart_struct_tostring(ofstream& out,
+void t_dart_generator::generate_dart_struct_tostring(ostream& out,
                                                    t_struct* tstruct) {
   indent(out) << "String toString()";
   scope_up(out);
@@ -1784,7 +1784,7 @@
  * @param tfield The field
  * @param prefix The variable name or container for this field
  */
-void t_dart_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_dart_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
   string field_name = get_member_name(tfield->get_name());
 
@@ -1850,7 +1850,7 @@
 /**
  * Generates an unserializer for a struct, invokes read()
  */
-void t_dart_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_dart_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl;
   indent(out) << prefix << ".read(iprot);" << endl;
 }
@@ -1858,7 +1858,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_dart_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_dart_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   indent(out);
   scope_up(out, "");
 
@@ -1915,7 +1915,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_dart_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_dart_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
@@ -1933,7 +1933,7 @@
 /**
  * Deserializes a set element
  */
-void t_dart_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_dart_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -1947,7 +1947,7 @@
 /**
  * Deserializes a list element
  */
-void t_dart_generator::generate_deserialize_list_element(ofstream& out,
+void t_dart_generator::generate_deserialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string prefix) {
   string elem = tmp("_elem");
@@ -1966,7 +1966,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_dart_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_dart_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
   string field_name = get_member_name(tfield->get_name());
 
@@ -2036,7 +2036,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_dart_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_dart_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << prefix << ".write(oprot);" << endl;
 }
@@ -2047,7 +2047,7 @@
  * @param ttype  The type of container
  * @param prefix String prefix for fields
  */
-void t_dart_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_dart_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   indent(out);
   scope_up(out, "");
 
@@ -2098,7 +2098,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_dart_generator::generate_serialize_map_element(ofstream& out,
+void t_dart_generator::generate_serialize_map_element(ostream& out,
                                                      t_map* tmap,
                                                      string iter,
                                                      string map) {
@@ -2111,7 +2111,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_dart_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_dart_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2119,7 +2119,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_dart_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_dart_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2194,7 +2194,7 @@
   if (init) {
     t_type* ttype = get_true_type(tfield->get_type());
     if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
+      std:: ofstream dummy;
       result += " = " + render_const_value(dummy, field_name, ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -2452,7 +2452,7 @@
 /**
  * Emits a doc comment if the provided object has a doc in Thrift
  */
-void t_dart_generator::generate_dart_doc(ofstream& out, t_doc* tdoc) {
+void t_dart_generator::generate_dart_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_docstring_comment(out, "", "/// ", tdoc->get_doc(), "");
   }
@@ -2461,7 +2461,7 @@
 /**
  * Emits a doc comment if the provided function object has a doc in Thrift
  */
-void t_dart_generator::generate_dart_doc(ofstream& out, t_function* tfunction) {
+void t_dart_generator::generate_dart_doc(ostream& out, t_function* tfunction) {
   if (tfunction->has_doc()) {
     stringstream ss;
     ss << tfunction->get_doc();
@@ -2488,7 +2488,7 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_dart_generator::generate_isset_set(ofstream& out, t_field* field) {
+void t_dart_generator::generate_isset_set(ostream& out, t_field* field) {
   if (!type_can_be_null(field->get_type())) {
     string field_name = get_member_name(field->get_name());
     indent(out) << "this.__isset_" << field_name << " = true;" << endl;
diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
index 1894fe8..8bd77e8 100644
--- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
@@ -65,6 +65,7 @@
     constprefix_ = false;
     events_ = false;
     xmldoc_ = false;
+    async_ = false;
     for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if( iter->first.compare("ansistr_binary") == 0) {
         ansistr_binary_ = true;
@@ -76,6 +77,8 @@
         events_ = true;
       } else if( iter->first.compare("xmldoc") == 0) {
         xmldoc_ = true;
+      } else if( iter->first.compare("async") == 0) {
+        async_ = true;
       } else {
         throw "unknown option delphi:" + iter->first;
       }
@@ -128,7 +131,7 @@
                                             bool is_xception_class,
                                             bool is_union,
                                             bool is_xception_factory,
-                                            std::string xception_factroy_name);
+                                            std::string xception_factory_name);
   void generate_delphi_clear_union_value(ostream& out,
                                          std::string cls_prefix,
                                          std::string name,
@@ -138,7 +141,7 @@
                                          bool is_xception_class,
                                          bool is_union,
                                          bool is_xception_factory,
-                                         std::string xception_factroy_name);
+                                         std::string xception_factory_name);
   void generate_delphi_isset_reader_impl(ostream& out,
                                          std::string cls_prefix,
                                          std::string name,
@@ -236,6 +239,7 @@
 
   void generate_function_helpers(t_function* tfunction);
   void generate_service_interface(t_service* tservice);
+  void generate_service_interface(t_service* tservice, bool for_async);
   void generate_service_helpers(t_service* tservice);
   void generate_service_client(t_service* tservice);
   void generate_service_server(t_service* tservice);
@@ -323,6 +327,7 @@
                             std::string prefix = "",
                             bool is_xception_class = false);
   std::string function_signature(t_function* tfunction,
+                                 bool for_async,
                                  std::string full_cls = "",
                                  bool is_xception = false);
   std::string argument_list(t_struct* tstruct);
@@ -399,6 +404,7 @@
   bool constprefix_;
   bool events_;
   bool xmldoc_;
+  bool async_;
   void indent_up_impl() { ++indent_impl_; };
   void indent_down_impl() { --indent_impl_; };
   std::string indent_impl() {
@@ -636,10 +642,21 @@
 
   // reserved/predefined variables and types (lowercase!)
   delphi_keywords["result"] = 1;
+  delphi_keywords["system"] = 1;
+  delphi_keywords["sysutils"] = 1;
+  delphi_keywords["thrift"] = 1;
   delphi_keywords["tbytes"] = 1;
   delphi_keywords["tobject"] = 1;
   delphi_keywords["tclass"] = 1;
   delphi_keywords["tinterfacedobject"] = 1;
+  delphi_keywords["ansistring"] = 1;
+  delphi_keywords["string"] = 1;
+  delphi_keywords["boolean"] = 1;
+  delphi_keywords["shortint"] = 1;
+  delphi_keywords["smallint"] = 1;
+  delphi_keywords["integer"] = 1;
+  delphi_keywords["int64"] = 1;
+  delphi_keywords["double"] = 1;
 
   delphi_reserved_method["create"] = 1;
   delphi_reserved_method["free"] = 1;
@@ -721,15 +738,19 @@
   has_enum = false;
   has_const = false;
   create_keywords();
+
   add_delphi_uses_list("Classes");
   add_delphi_uses_list("SysUtils");
   add_delphi_uses_list("Generics.Collections");
+  if(async_) {
+    add_delphi_uses_list("System.Threading");
+  }
+
   add_delphi_uses_list("Thrift");
   add_delphi_uses_list("Thrift.Utils");
   add_delphi_uses_list("Thrift.Collections");
   add_delphi_uses_list("Thrift.Protocol");
   add_delphi_uses_list("Thrift.Transport");
-
   if (register_types_) {
     add_delphi_uses_list("Thrift.TypeRegistry");
   }
@@ -742,7 +763,7 @@
     unitname = includes[i]->get_name();
     nsname = includes[i]->get_namespace("delphi");
     if ("" != nsname) {
-      unitname = nsname;
+      unitname = normalize_name(nsname);
     }
     add_delphi_uses_list(unitname);
   }
@@ -762,8 +783,10 @@
     }
   }
 
+  unitname = normalize_name(unitname);
+  
   std::string f_name = get_out_dir() + "/" + unitname + ".pas";
-  std::ofstream f_all;
+  ofstream_with_content_based_conditional_update f_all;
 
   f_all.open(f_name.c_str());
 
@@ -1195,8 +1218,8 @@
   if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -1215,8 +1238,8 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(vars, out, name, ktype, v_iter->first);
       string val = render_const_value(vars, out, name, vtype, v_iter->second);
@@ -1460,8 +1483,6 @@
   indent_up_impl();
   if (is_exception && (!is_x_factory)) {
     indent_impl(out) << "inherited Create('');" << endl;
-    indent_impl(out) << "F" << exception_factory_name << " := T" << exception_factory_name
-                     << "Impl.Create;" << endl;
   } else {
     indent_impl(out) << "inherited;" << endl;
   }
@@ -1507,6 +1528,19 @@
   indent_down_impl();
   indent_impl(out) << "end;" << endl << endl;
 
+  if (is_exception && (!is_x_factory)) {
+    indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name
+                     << ": I" << exception_factory_name << ";" << endl;
+    indent_impl(out) << "begin" << endl;
+    indent_up_impl();
+    indent_impl(out) << "if F" << exception_factory_name << " = nil" << endl;
+    indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl;
+    indent_impl(out) << endl;
+    indent_impl(out) << "result := F" << exception_factory_name << ";" << endl;
+    indent_down_impl();
+    indent_impl(out) << "end;" << endl << endl;
+  }
+
   if (tstruct->is_union()) {
     indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
                      << "ClearUnionValues;" << endl;
@@ -1692,7 +1726,7 @@
       for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
         if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
           isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-          indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
+          indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << ";"
                       << endl;
         }
       }
@@ -1741,7 +1775,7 @@
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
         isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << isset_name << ": Boolean;" << endl;
+        indent(out) << isset_name << ": System.Boolean;" << endl;
       }
     }
   }
@@ -1764,7 +1798,7 @@
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
         isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << "function Get" << isset_name << ": Boolean;" << endl;
+        indent(out) << "function Get" << isset_name << ": System.Boolean;" << endl;
       }
     }
   }
@@ -1790,8 +1824,7 @@
   if (is_exception && (!is_x_factory)) {
     out << endl;
     indent(out) << "// Exception Factory" << endl;
-    indent(out) << "property " << exception_factory_name << ": " << struct_intf_name << " read F"
-                << exception_factory_name << " write F" << exception_factory_name << ";" << endl;
+    indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << endl;
   }
 
   if ((!is_exception) || is_x_factory) {
@@ -1821,7 +1854,7 @@
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
         isset_name = "__isset_" + prop_name(*m_iter, is_exception);
-        indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";"
+        indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << ";"
                     << endl;
       }
     }
@@ -1850,19 +1883,28 @@
 }
 
 void t_delphi_generator::generate_service_interface(t_service* tservice) {
+  generate_service_interface(tservice,false);
+  if(async_) {
+    generate_service_interface(tservice,true);
+  }
+}
+
+
+void t_delphi_generator::generate_service_interface(t_service* tservice, bool for_async) {
   string extends = "";
   string extends_iface = "";
+  string iface_name = for_async ? "IAsync" : "Iface";
 
   indent_up();
 
   generate_delphi_doc(s_service, tservice);
   if (tservice->get_extends() != NULL) {
     extends = type_name(tservice->get_extends(), true, true);
-    extends_iface = extends + ".Iface";
+    extends_iface = extends + "." + iface_name;
     generate_delphi_doc(s_service, tservice);
-    indent(s_service) << "Iface = interface(" << extends_iface << ")" << endl;
+    indent(s_service) << iface_name << " = interface(" << extends_iface << ")" << endl;
   } else {
-    indent(s_service) << "Iface = interface" << endl;
+    indent(s_service) << iface_name << " = interface" << endl;
   }
 
   indent_up();
@@ -1870,7 +1912,7 @@
   vector<t_function*>::iterator f_iter;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     generate_delphi_doc(s_service, *f_iter);
-    indent(s_service) << function_signature(*f_iter) << endl;
+    indent(s_service) << function_signature(*f_iter, for_async) << endl;
   }
   indent_down();
   indent(s_service) << "end;" << endl << endl;
@@ -1896,20 +1938,15 @@
 void t_delphi_generator::generate_service_client(t_service* tservice) {
   indent_up();
   string extends = "";
-  string extends_client = "";
-  if (tservice->get_extends() != NULL) {
-    extends = type_name(tservice->get_extends());
-    extends_client = extends + ".Client, ";
-  }
+  string extends_client = "TInterfacedObject";
+  string implements = async_ ? "Iface, IAsync" : "Iface";
 
   generate_delphi_doc(s_service, tservice);
   if (tservice->get_extends() != NULL) {
     extends = type_name(tservice->get_extends(), true, true);
     extends_client = extends + ".TClient";
-    indent(s_service) << "TClient = class(" << extends_client << ", Iface)" << endl;
-  } else {
-    indent(s_service) << "TClient = class( TInterfacedObject, Iface)" << endl;
   }
+  indent(s_service) << "TClient = class( " << extends_client << ", " << implements << ")" << endl;
 
   indent(s_service) << "public" << endl;
   indent_up();
@@ -1945,7 +1982,7 @@
     indent_up();
     indent(s_service) << "iprot_: IProtocol;" << endl;
     indent(s_service) << "oprot_: IProtocol;" << endl;
-    indent(s_service) << "seqid_: Integer;" << endl;
+    indent(s_service) << "seqid_: System.Integer;" << endl;
     indent_down();
 
     indent(s_service) << "public" << endl;
@@ -1960,12 +1997,24 @@
 
   indent(s_service) << "protected" << endl;
   indent_up();
+
   indent(s_service) << "// Iface" << endl;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     string funname = (*f_iter)->get_name();
     generate_delphi_doc(s_service, *f_iter);
-    indent(s_service) << function_signature(*f_iter) << endl;
+    indent(s_service) << function_signature(*f_iter, false) << endl;
   }
+
+  if( async_) {
+    indent(s_service) << endl;
+    indent(s_service) << "// IAsync" << endl;
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      string funname = (*f_iter)->get_name();
+      generate_delphi_doc(s_service, *f_iter);
+      indent(s_service) << function_signature(*f_iter, true) << endl;
+    }
+  }
+
   indent_down();
 
   indent(s_service) << "public" << endl;
@@ -1976,36 +2025,65 @@
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     string funname = (*f_iter)->get_name();
 
-    indent_impl(s_service_impl) << function_signature(*f_iter, full_cls) << endl;
-    indent_impl(s_service_impl) << "begin" << endl;
-    indent_up_impl();
-    indent_impl(s_service_impl) << "send_" << funname << "(";
-
-    t_struct* arg_struct = (*f_iter)->get_arglist();
-
-    const vector<t_field*>& fields = arg_struct->get_members();
     vector<t_field*>::const_iterator fld_iter;
-    bool first = true;
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-      if (first) {
-        first = false;
-      } else {
-        s_service_impl << ", ";
-      }
-      s_service_impl << normalize_name((*fld_iter)->get_name());
-    }
-    s_service_impl << ");" << endl;
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
 
-    if (!(*f_iter)->is_oneway()) {
-      s_service_impl << indent_impl();
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        s_service_impl << "Result := ";
-      }
-      s_service_impl << "recv_" << funname << "();" << endl;
-    }
+    // one for sync only, two for async+sync
+    int mode = async_ ? 1 : 0;
+    while( mode >= 0) {
+      bool for_async = (mode != 0);
+      mode--;
 
-    indent_down_impl();
-    indent_impl(s_service_impl) << "end;" << endl << endl;
+      indent_impl(s_service_impl) << function_signature(*f_iter, for_async, full_cls) << endl;
+      indent_impl(s_service_impl) << "begin" << endl;
+      indent_up_impl();
+
+      t_type* ttype = (*f_iter)->get_returntype();
+      if( for_async) {
+        if (is_void(ttype)) {
+           // Delphi forces us to specify a type with IFuture<T>, so we use Integer=0 for void methods
+          indent_impl(s_service_impl) << "result := TTask.Future<System.Integer>(function: System.Integer" << endl;
+        } else {
+          string rettype = type_name(ttype, false, true, false, true);
+          indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << endl;
+        }
+        indent_impl(s_service_impl) << "begin" << endl;
+        indent_up_impl();
+      }
+
+      indent_impl(s_service_impl) << "send_" << funname << "(";
+
+      bool first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          s_service_impl << ", ";
+        }
+        s_service_impl << normalize_name((*fld_iter)->get_name());
+      }
+      s_service_impl << ");" << endl;
+
+      if (!(*f_iter)->is_oneway()) {
+        s_service_impl << indent_impl();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          s_service_impl << "Result := ";
+        }
+        s_service_impl << "recv_" << funname << "();" << endl;
+      }
+
+      if( for_async) {
+        if (is_void(ttype)) {
+          indent_impl(s_service_impl) << "Result := 0;" << endl;  // no IFuture<void> in Delphi
+        }
+        indent_down_impl();
+        indent_impl(s_service_impl) << "end);" << endl;
+      }
+
+      indent_down_impl();
+      indent_impl(s_service_impl) << "end;" << endl << endl;
+    }
 
     t_function send_function(g_type_void,
                              string("send_") + (*f_iter)->get_name(),
@@ -2018,8 +2096,8 @@
     string argsvar = tmp("_args");
     string msgvar = tmp("_msg");
 
-    indent(s_service) << function_signature(&send_function) << endl;
-    indent_impl(s_service_impl) << function_signature(&send_function, full_cls) << endl;
+    indent(s_service) << function_signature(&send_function, false) << endl;
+    indent_impl(s_service_impl) << function_signature(&send_function, false, full_cls) << endl;
     indent_impl(s_service_impl) << "var" << endl;
     indent_up_impl();
     indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl;
@@ -2072,8 +2150,8 @@
       string appexvar = tmp("_ax");
       string retvar = tmp("_ret");
 
-      indent(s_service) << function_signature(&recv_function) << endl;
-      indent_impl(s_service_impl) << function_signature(&recv_function, full_cls) << endl;
+      indent(s_service) << function_signature(&recv_function, false) << endl;
+      indent_impl(s_service_impl) << function_signature(&recv_function, false, full_cls) << endl;
       indent_impl(s_service_impl) << "var" << endl;
       indent_up_impl();
       indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.TThriftMessage;" << endl;
@@ -2131,7 +2209,7 @@
 
       if (!(*f_iter)->get_returntype()->is_void()) {
         indent_impl(s_service_impl)
-			<< "raise TApplicationExceptionMissingResult.Create('"
+            << "raise TApplicationExceptionMissingResult.Create('"
             << (*f_iter)->get_name() << " failed: unknown result');" << endl;
       }
 
@@ -2207,7 +2285,7 @@
     indent_up();
     indent(s_service) << "type" << endl;
     indent_up();
-    indent(s_service) << "TProcessFunction = reference to procedure( seqid: Integer; const iprot: "
+    indent(s_service) << "TProcessFunction = reference to procedure( seqid: System.Integer; const iprot: "
                          "IProtocol; const oprot: IProtocol"
                       << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
     indent_down();
@@ -2222,15 +2300,15 @@
   indent_up();
   if (extends.empty()) {
     indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
-                         "events : IProcessorEvents): Boolean;" << endl;
+                         "events : IProcessorEvents): System.Boolean;" << endl;
   } else {
     indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
-                         "events : IProcessorEvents): Boolean; reintroduce;" << endl;
+                         "events : IProcessorEvents): System.Boolean; reintroduce;" << endl;
   }
 
   indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; "
                                                             "const oprot: IProtocol; const events "
-                                                            ": IProcessorEvents): Boolean;" << endl;
+                                                            ": IProcessorEvents): System.Boolean;" << endl;
   ;
   indent_impl(s_service_impl) << "var" << endl;
   indent_up_impl();
@@ -2254,8 +2332,8 @@
   indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
   indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
   indent_impl(s_service_impl) << "x := "
-								 "TApplicationExceptionUnknownMethod.Create("
-								 "'Invalid method name: ''' + msg.Name + '''');" << endl;
+                                 "TApplicationExceptionUnknownMethod.Create("
+                                 "'Invalid method name: ''' + msg.Name + '''');" << endl;
   indent_impl(s_service_impl)
       << "Thrift.Protocol.Init( msg, msg.Name, TMessageType.Exception, msg.SeqID);"
       << endl;
@@ -2356,7 +2434,7 @@
   string result_intfnm = normalize_clsnm(org_resultname, "I");
 
   indent(s_service) << "procedure " << funcname
-                    << "_Process( seqid: Integer; const iprot: IProtocol; const oprot: IProtocol"
+                    << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol"
                     << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
 
   if (tfunction->is_oneway()) {
@@ -2367,7 +2445,7 @@
 
   indent_impl(s_service_impl)
       << "procedure " << full_cls << "." << funcname
-      << "_Process( seqid: Integer; const iprot: IProtocol; const oprot: IProtocol"
+      << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol"
       << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
   indent_impl(s_service_impl) << "var" << endl;
   indent_up_impl();
@@ -2452,7 +2530,7 @@
     indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl;
   }
   if (!tfunction->is_oneway()) {
-	indent_impl(s_service_impl) << "appx := TApplicationExceptionInternalError.Create(E.Message);"
+    indent_impl(s_service_impl) << "appx := TApplicationExceptionInternalError.Create(E.Message);"
                                 << endl;
     indent_impl(s_service_impl) << "try" << endl;
     indent_up_impl();
@@ -2627,7 +2705,7 @@
   }
   local_vars << "  " << local_var << endl;
   counter = tmp("_i");
-  local_var = counter + ": Integer;";
+  local_var = counter + ": System.Integer;";
   local_vars << "  " << local_var << endl;
 
   indent_impl(out) << name << " := " << type_name(ttype, true) << ".Create;" << endl;
@@ -2775,7 +2853,7 @@
         throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase);
       }
     } else if (type->is_enum()) {
-      out << "WriteI32(Integer(" << name << "));";
+      out << "WriteI32(System.Integer(" << name << "));";
     }
     out << endl;
   } else {
@@ -3086,25 +3164,25 @@
   case t_base_type::TYPE_STRING:
     if (tbase->is_binary()) {
       if (ansistr_binary_) {
-        return "AnsiString";
+        return "System.AnsiString";
       } else {
-        return "TBytes";
+        return "SysUtils.TBytes";
       }
     } else {
-      return "string";
+      return "System.string";
     }
   case t_base_type::TYPE_BOOL:
-    return "Boolean";
+    return "System.Boolean";
   case t_base_type::TYPE_I8:
-    return "ShortInt";
+    return "System.ShortInt";
   case t_base_type::TYPE_I16:
-    return "SmallInt";
+    return "System.SmallInt";
   case t_base_type::TYPE_I32:
-    return "Integer";
+    return "System.Integer";
   case t_base_type::TYPE_I64:
-    return "Int64";
+    return "System.Int64";
   case t_base_type::TYPE_DOUBLE:
-    return "Double";
+    return "System.Double";
   default:
     throw "compiler error: no Delphi name for base type "
         + t_base_type::t_base_name(tbase->get_base());
@@ -3126,6 +3204,7 @@
 }
 
 string t_delphi_generator::function_signature(t_function* tfunction,
+                                              bool for_async,
                                               std::string full_cls,
                                               bool is_xception) {
   t_type* ttype = tfunction->get_returntype();
@@ -3135,13 +3214,25 @@
   } else {
     prefix = full_cls + ".";
   }
-  if (is_void(ttype)) {
-    return "procedure " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
-           + argument_list(tfunction->get_arglist()) + ");";
+
+  if( for_async) {
+    if (is_void(ttype)) {
+      return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
+             + argument_list(tfunction->get_arglist()) + "): IFuture<Integer>;";  // no IFuture<void> in Delphi
+    } else {
+      return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
+             + argument_list(tfunction->get_arglist()) + "): IFuture<"
+             + type_name(ttype, false, true, is_xception, true) + ">;";
+    }
   } else {
-    return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
-           + argument_list(tfunction->get_arglist()) + "): "
-           + type_name(ttype, false, true, is_xception, true) + ";";
+    if (is_void(ttype)) {
+      return "procedure " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
+             + argument_list(tfunction->get_arglist()) + ");";
+    } else {
+      return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
+             + argument_list(tfunction->get_arglist()) + "): "
+             + type_name(ttype, false, true, is_xception, true) + ";";
+    }
   }
 }
 
@@ -3326,7 +3417,7 @@
 void t_delphi_generator::generate_delphi_isset_reader_definition(ostream& out,
                                                                  t_field* tfield,
                                                                  bool is_xception) {
-  indent(out) << "function Get__isset_" << prop_name(tfield, is_xception) << ": Boolean;" << endl;
+  indent(out) << "function Get__isset_" << prop_name(tfield, is_xception) << ": System.Boolean;" << endl;
 }
 
 void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
@@ -3369,7 +3460,7 @@
                                                               bool is_xception_class,
                                                               bool is_union,
                                                               bool is_xception_factory,
-                                                              std::string xception_factroy_name) {
+                                                              std::string xception_factory_name) {
   (void)type;
 
   t_type* ftype = tfield->get_type();
@@ -3390,7 +3481,7 @@
   indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := Value;" << endl;
 
   if (is_xception_class && (!is_xception_factory)) {
-    indent_impl(out) << "F" << xception_factroy_name << "." << prop_name(tfield, is_xception_class)
+    indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class)
                      << " := Value;" << endl;
   }
 
@@ -3432,7 +3523,7 @@
 
   string isset_name = "__isset_" + prop_name(tfield, is_xception);
   indent_impl(out) << "function " << cls_prefix << name << "."
-                   << "Get" << isset_name << ": Boolean;" << endl;
+                   << "Get" << isset_name << ": System.Boolean;" << endl;
   indent_impl(out) << "begin" << endl;
   indent_up_impl();
   indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << endl;
@@ -3457,7 +3548,7 @@
 
   indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << endl;
   string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-  indent_impl(out) << "Result." << factory_name << " := Self;" << endl;
+  indent_impl(out) << "Result.F" << factory_name << " := Self;" << endl;
 
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -3467,8 +3558,7 @@
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     propname = prop_name(*f_iter, is_exception);
     if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
-      indent_impl(out) << "if __isset_" << propname << " then" << endl;
-      indent_impl(out) << "begin" << endl;
+      indent_impl(out) << "if __isset_" << propname << " then begin" << endl;
       indent_up_impl();
     }
     indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl;
@@ -3504,7 +3594,7 @@
   // local bools for required fields
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      indent_impl(local_vars) << "_req_isset_" << prop_name(*f_iter, is_exception) << " : Boolean;"
+      indent_impl(local_vars) << "_req_isset_" << prop_name(*f_iter, is_exception) << " : System.Boolean;"
                               << endl;
       indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := FALSE;"
                               << endl;
@@ -3721,7 +3811,7 @@
     if (is_required && null_allowed) {
       null_allowed = false;
       indent_impl(code_block) << "if (Self." << fieldname << " = nil)" << endl;
-	  indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create("
+      indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create("
                               << "'required field " << fieldname << " not set');"
                               << endl;
     }
@@ -3802,7 +3892,7 @@
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED);
     if (is_optional) {
-      indent_impl(out) << tmp_first << " : Boolean;" << endl;
+      indent_impl(out) << tmp_first << " : System.Boolean;" << endl;
       useFirstFlag = true;
     }
     break;
@@ -3861,7 +3951,7 @@
                        << ".Append('<null>') else " << tmp_sb << ".Append( Self."
                        << prop_name((*f_iter), is_exception) << ".ToString());" << endl;
     } else if (ttype->is_enum()) {
-      indent_impl(out) << tmp_sb << ".Append(Integer( Self." << prop_name((*f_iter), is_exception)
+      indent_impl(out) << tmp_sb << ".Append(System.Integer( Self." << prop_name((*f_iter), is_exception)
                        << "));" << endl;
     } else {
       indent_impl(out) << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ");"
@@ -3917,4 +4007,5 @@
     "                     and container instances by interface or TypeInfo()\n"
     "    constprefix:     Name TConstants classes after IDL to reduce ambiguities\n"
     "    events:          Enable and use processing events in the generated code.\n"
-    "    xmldoc:          Enable XMLDoc comments for Help Insight etc.\n")
+    "    xmldoc:          Enable XMLDoc comments for Help Insight etc.\n"
+    "    async:           Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n")
diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc
index 372c78b..12d91a7 100644
--- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc
@@ -220,15 +220,15 @@
   std::ostringstream f_info_;
   std::ostringstream f_info_ext_;
 
-  std::ofstream f_types_file_;
-  std::ofstream f_types_hrl_file_;
+  ofstream_with_content_based_conditional_update f_types_file_;
+  ofstream_with_content_based_conditional_update f_types_hrl_file_;
 
-  std::ofstream f_consts_file_;
-  std::ofstream f_consts_hrl_file_;
+  ofstream_with_content_based_conditional_update f_consts_file_;
+  ofstream_with_content_based_conditional_update f_consts_hrl_file_;
 
   std::ostringstream f_service_;
-  std::ofstream f_service_file_;
-  std::ofstream f_service_hrl_;
+  ofstream_with_content_based_conditional_update f_service_file_;
+  ofstream_with_content_based_conditional_update f_service_hrl_;
 
   /**
    * Metadata containers
@@ -384,8 +384,37 @@
   f_consts_hrl_file_.close();
 }
 
+const std::string emit_double_as_string(const double value) {
+  std::stringstream double_output_stream;
+  // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision
+  // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation)
+  double_output_stream << std::setprecision(std::numeric_limits<double>::digits10 + 1);
+
+  #ifdef _MSC_VER
+      // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal.
+      // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/
+      //               c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
+      //               and
+      //               http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/
+      #if _MSC_VER >= MSC_2015_VER
+          double_output_stream << std::fixed;
+      #else
+          // note that if this function is called from the erlang generator and the MSVC compiler is older than 2015,
+          // the double literal must be output in the scientific format. There can be some cases where the
+          // mantissa of the output does not have fractionals, which is illegal in Erlang.
+          // example => 10000000000000000.0 being output as 1e+16
+          double_output_stream << std::scientific;
+      #endif
+  #else
+      double_output_stream << std::fixed;
+  #endif
+
+  double_output_stream << value;
+
+  return double_output_stream.str();
+}
+
 void t_erl_generator::generate_type_metadata(std::string function_name, vector<string> names) {
-  vector<string>::iterator s_iter;
   size_t num_structs = names.size();
 
   indent(f_types_file_) << function_name << "() ->\n";
@@ -430,7 +459,7 @@
     exports << const_fun_name << "/1, " << const_fun_name << "/2";
 
     // Emit const function definition.
-    map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator i, end = value->get_map().end();
     // The one-argument form throws an error if the key does not exist in the map.
     for (i = value->get_map().begin(); i != end;) {
       functions << const_fun_name << "(" << render_const_value(ktype, i->first) << ") -> "
@@ -575,9 +604,9 @@
       break;
     case t_base_type::TYPE_DOUBLE:
       if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
+        out << "float(" << value->get_integer() << ")";
       } else {
-        out << value->get_double();
+        out << emit_double_as_string(value->get_double());
       }
       break;
     default:
@@ -590,8 +619,8 @@
     out << "#" << type_name(type) << "{";
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     bool first = true;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
@@ -626,7 +655,7 @@
     } else {
       out << "dict:from_list([";
     }
-    map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator i, end = value->get_map().end();
     for (i = value->get_map().begin(); i != end;) {
       out << "{" << render_const_value(ktype, i->first) << ","
           << render_const_value(vtype, i->second) << "}";
@@ -717,7 +746,7 @@
     return type_name(type) + "()";
   } else if (type->is_map()) {
     if (maps_) {
-      return "#{}";
+      return "map()";
     } else if (otp16_) {
       return "dict()";
     } else {
@@ -810,6 +839,8 @@
   if (has_default_value(tmember))
     out << " = " << render_member_value(tmember);
   out << " :: " << render_member_type(tmember);
+  if (tmember->get_req() != t_field::T_REQUIRED)
+    out << " | 'undefined'";
 }
 
 bool t_erl_generator::has_default_value(t_field* field) {
@@ -915,7 +946,6 @@
 void t_erl_generator::generate_service_metadata(t_service* tservice) {
   export_string("function_names", 0);
   vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
   size_t num_functions = functions.size();
 
   indent(f_service_) << "function_names() -> " << endl;
diff --git a/compiler/cpp/src/thrift/generate/t_generator.cc b/compiler/cpp/src/thrift/generate/t_generator.cc
index 0c1f49d..ca3f5dd 100644
--- a/compiler/cpp/src/thrift/generate/t_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_generator.cc
@@ -76,6 +76,77 @@
   close_generator();
 }
 
+std::set<std::string> t_generator::lang_keywords() const {
+  std::string keywords[] = { "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__",
+      "__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as",
+      "assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare",
+      "def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif",
+      "end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure",
+      "except", "exec", "finally", "float", "for", "foreach", "from", "function", "global",
+      "goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is",
+      "lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass",
+      "public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register",
+      "return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this",
+      "throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var",
+      "virtual", "volatile", "when", "while", "with", "xor", "yield" };
+  return std::set<std::string>(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) );
+}
+
+void t_generator::validate_input() const {
+  validate(program_->get_enums());
+  validate(program_->get_typedefs());
+  validate(program_->get_objects());
+  validate(program_->get_consts());
+  validate(program_->get_services());
+}
+
+template <typename T>
+void t_generator::validate(const vector<T>& list) const{
+  typename vector<T>::const_iterator it;
+  for(it=list.begin(); it != list.end(); ++it) {
+      validate(*it);
+  }
+}
+
+void t_generator::validate(t_function const* f) const {
+  validate_id(f->get_name());
+  validate(f->get_arglist());
+  validate(f->get_xceptions());
+}
+
+void t_generator::validate(t_service const* s) const {
+  validate_id(s->get_name());
+  validate(s->get_functions());
+}
+
+void t_generator::validate(t_enum const* en) const {
+  validate_id(en->get_name());
+  validate(en->get_constants());
+}
+void t_generator::validate(t_struct const* s) const {
+  validate_id(s->get_name());
+  validate(s->get_members());
+}
+
+void t_generator::validate(t_enum_value const* en_val) const {
+  validate_id(en_val->get_name());
+}
+void t_generator::validate(t_typedef const* td) const {
+  validate_id(td->get_name());
+}
+void t_generator::validate(t_const const* c) const {
+  validate_id(c->get_name());
+}
+void t_generator::validate(t_field const* f) const {
+  validate_id(f->get_name());
+}
+
+void t_generator::validate_id(const string& id) const {
+  if (keywords_.find(id) != keywords_.end()) {
+    failure("Cannot use reserved language keyword: \"%s\"", id.c_str());
+  }
+}
+
 string t_generator::escape_string(const string& in) const {
   string result = "";
   for (string::const_iterator it = in.begin(); it < in.end(); it++) {
@@ -101,21 +172,22 @@
                                              const string& line_prefix,
                                              const string& contents,
                                              const string& comment_end) {
-  if (comment_start != "")
+  if (!comment_start.empty())
     indent(out) << comment_start;
   stringstream docs(contents, ios_base::in);
   while (!(docs.eof() || docs.fail())) {
     char line[1024];
     docs.getline(line, 1024);
 
-    // Just prnt a newline when the line & prefix are empty.
-    if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) {
-      out << std::endl;
-    } else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
+    if (strlen(line) > 0) {
       indent(out) << line_prefix << line << std::endl;
+    } else if (line_prefix.empty()){
+      out << std::endl;
+    } else if(!docs.eof()) {
+      indent(out) << line_prefix << std::endl;
     }
   }
-  if (comment_end != "")
+  if (!comment_end.empty())
     indent(out) << comment_end;
 }
 
diff --git a/compiler/cpp/src/thrift/generate/t_generator.h b/compiler/cpp/src/thrift/generate/t_generator.h
index fc3f323..cb9d076 100644
--- a/compiler/cpp/src/thrift/generate/t_generator.h
+++ b/compiler/cpp/src/thrift/generate/t_generator.h
@@ -19,12 +19,17 @@
 
 #ifndef T_GENERATOR_H
 #define T_GENERATOR_H
+#define MSC_2015_VER 1900
 
+#include <cstring>
 #include <string>
+#include <iomanip>
 #include <iostream>
 #include <fstream>
+#include <limits>
 #include <sstream>
 #include "thrift/common.h"
+#include "thrift/logging.h"
 #include "thrift/version.h"
 #include "thrift/generate/t_generator_registry.h"
 #include "thrift/parse/t_program.h"
@@ -37,7 +42,8 @@
  */
 class t_generator {
 public:
-  t_generator(t_program* program) {
+  t_generator(t_program* program)
+    : keywords_(lang_keywords()){
     tmp_ = 0;
     indent_ = 0;
     program_ = program;
@@ -91,9 +97,35 @@
     return escape_string(constval->get_string());
   }
 
-protected:
   /**
-   * Optional methods that may be imlemented by subclasses to take necessary
+   * Check if all identifiers are valid for the target language
+   */
+  virtual void validate_input() const;
+
+protected:
+  virtual std::set<std::string> lang_keywords() const;
+
+  /**
+   * A list of reserved words that cannot be used as identifiers.
+   */
+  const std::set<std::string> keywords_;
+
+  virtual void validate_id(const std::string& id) const;
+
+  virtual void validate(t_enum const* en) const;
+  virtual void validate(t_enum_value const* en_val) const;
+  virtual void validate(t_typedef const* td) const;
+  virtual void validate(t_const const* c) const;
+  virtual void validate(t_service const* s) const;
+  virtual void validate(t_struct const* c) const;
+  virtual void validate(t_field const* f) const;
+  virtual void validate(t_function const* f) const;
+
+  template <typename T>
+  void validate(const std::vector<T>& list) const;
+
+  /**
+   * Optional methods that may be implemented by subclasses to take necessary
    * steps at the beginning or end of code generation.
    */
 
@@ -183,7 +215,6 @@
     }
   }
 
-
   /**
    * Indentation print function
    */
@@ -224,6 +255,7 @@
     }
     return in;
   }
+
   /**
    * Transforms a camel case string to an equivalent one separated by underscores
    * e.g. aMultiWord -> a_multi_word
@@ -242,6 +274,7 @@
     }
     return in;
   }
+
   /**
     * Transforms a string with words separated by underscores to a camel case equivalent
     * e.g. a_multi_word -> aMultiWord
@@ -268,6 +301,30 @@
     return out.str();
   }
 
+  const std::string emit_double_as_string(const double value) {
+      std::stringstream double_output_stream;
+      // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision
+      // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation)
+      double_output_stream << std::setprecision(std::numeric_limits<double>::digits10 + 1);
+
+      #ifdef _MSC_VER
+          // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal.
+          // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/
+          //               c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
+          //               and
+          //               http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/
+          #if _MSC_VER >= MSC_2015_VER
+              double_output_stream << std::fixed;
+          #endif
+      #else
+          double_output_stream << std::fixed;
+      #endif
+
+      double_output_stream << value;
+
+      return double_output_stream.str();
+  }
+
 public:
   /**
    * Get the true type behind a series of typedefs.
@@ -319,4 +376,77 @@
   int tmp_;
 };
 
+template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
+class template_ofstream_with_content_based_conditional_update : public std::ostringstream {
+public:
+  template_ofstream_with_content_based_conditional_update(): contents_written(false) {}
+
+  template_ofstream_with_content_based_conditional_update(std::string const& output_file_path_)
+  : output_file_path(output_file_path_), contents_written(false) {}
+
+  ~template_ofstream_with_content_based_conditional_update() {
+    if (!contents_written) {
+      close();
+    }
+  }
+
+  void open(std::string const& output_file_path_) {
+    output_file_path = output_file_path_;
+    clear_buf();
+    contents_written = false;
+  }
+
+  void close() {
+    if (contents_written || output_file_path == "")
+      return;
+
+    if (!is_readable(output_file_path)) {
+      dump();
+      return;
+    }
+
+    std::ifstream old_file;
+    old_file.exceptions(old_file.exceptions() | std::ifstream::badbit | std::ifstream::failbit);
+    old_file.open(output_file_path.c_str(), std::ios::in);
+
+    if (old_file) {
+      std::string const old_file_contents(static_cast<std::ostringstream const&>(std::ostringstream() << old_file.rdbuf()).str());
+      old_file.close();
+
+      if (old_file_contents != str()) {
+        dump();
+      }
+    }
+  }
+
+protected:
+  void dump() {
+    std::ofstream out_file;
+    out_file.exceptions(out_file.exceptions() | std::ofstream::badbit | std::ofstream::failbit);
+    try {
+      out_file.open(output_file_path.c_str(), std::ios::out);
+    }
+    catch (const std::ios_base::failure& e) {
+      ::failure("failed to write the output to the file '%s', details: '%s'", output_file_path.c_str(), e.what());
+    }
+    out_file << str();
+    out_file.close();
+    clear_buf();
+    contents_written = true;
+  }
+
+  void clear_buf() {
+    str(std::string());
+  }
+
+  static bool is_readable(std::string const& file_name) {
+    return static_cast<bool>(std::ifstream(file_name.c_str()));
+  }
+
+private:
+  std::string output_file_path;
+  bool contents_written;
+};
+typedef template_ofstream_with_content_based_conditional_update<char> ofstream_with_content_based_conditional_update;
+
 #endif
diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc
index 6cce32b..ec16b87 100644
--- a/compiler/cpp/src/thrift/generate/t_go_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc
@@ -42,7 +42,7 @@
 #include "thrift/generate/t_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -61,7 +61,7 @@
  */
 bool format_go_output(const string& file_path);
 
-const string DEFAULT_THRIFT_IMPORT = "git.apache.org/thrift.git/lib/go/thrift";
+const string DEFAULT_THRIFT_IMPORT = "github.com/apache/thrift/lib/go/thrift";
 static std::string package_flag;
 
 /**
@@ -81,7 +81,6 @@
     gen_package_prefix_ = "";
     package_flag = "";
     read_write_private_ = false;
-    legacy_context_ = false;
     ignore_initialisms_ = false;
     for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if( iter->first.compare("package_prefix") == 0) {
@@ -92,8 +91,6 @@
         package_flag = (iter->second);
       } else if( iter->first.compare("read_write_private") == 0) {
         read_write_private_ = true;
-      } else if( iter->first.compare("legacy_context") == 0) {
-        legacy_context_ = true;
       } else if( iter->first.compare("ignore_initialisms") == 0) {
         ignore_initialisms_ =  true;
       } else {
@@ -122,34 +119,34 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  std::string render_const_value(t_type* type, t_const_value* value, const string& name);
+  std::string render_const_value(t_type* type, t_const_value* value, const string& name, bool opt = false);
 
   /**
    * Struct generation code
    */
 
   void generate_go_struct(t_struct* tstruct, bool is_exception);
-  void generate_go_struct_definition(std::ofstream& out,
+  void generate_go_struct_definition(std::ostream& out,
                                      t_struct* tstruct,
                                      bool is_xception = false,
                                      bool is_result = false,
                                      bool is_args = false);
-  void generate_go_struct_initializer(std::ofstream& out,
+  void generate_go_struct_initializer(std::ostream& out,
                                       t_struct* tstruct,
                                       bool is_args_or_result = false);
-  void generate_isset_helpers(std::ofstream& out,
+  void generate_isset_helpers(std::ostream& out,
                               t_struct* tstruct,
                               const string& tstruct_name,
                               bool is_result = false);
-  void generate_countsetfields_helper(std::ofstream& out,
+  void generate_countsetfields_helper(std::ostream& out,
                                       t_struct* tstruct,
                                       const string& tstruct_name,
                                       bool is_result = false);
-  void generate_go_struct_reader(std::ofstream& out,
+  void generate_go_struct_reader(std::ostream& out,
                                  t_struct* tstruct,
                                  const string& tstruct_name,
                                  bool is_result = false);
-  void generate_go_struct_writer(std::ofstream& out,
+  void generate_go_struct_writer(std::ostream& out,
                                  t_struct* tstruct,
                                  const string& tstruct_name,
                                  bool is_result = false,
@@ -174,7 +171,7 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   bool declare,
                                   std::string prefix = "",
@@ -183,64 +180,64 @@
                                   bool inkey = false,
                                   bool in_container = false);
 
-  void generate_deserialize_struct(std::ofstream& out,
+  void generate_deserialize_struct(std::ostream& out,
                                    t_struct* tstruct,
                                    bool is_pointer_field,
                                    bool declare,
                                    std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out,
+  void generate_deserialize_container(std::ostream& out,
                                       t_type* ttype,
                                       bool pointer_field,
                                       bool declare,
                                       std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out,
+  void generate_deserialize_set_element(std::ostream& out,
                                         t_set* tset,
                                         bool declare,
                                         std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out,
+  void generate_deserialize_map_element(std::ostream& out,
                                         t_map* tmap,
                                         bool declare,
                                         std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          bool declare,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out,
+  void generate_serialize_field(std::ostream& out,
                                 t_field* tfield,
                                 std::string prefix = "",
                                 bool inkey = false);
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out,
+  void generate_serialize_container(std::ostream& out,
                                     t_type* ttype,
                                     bool pointer_field,
                                     std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_go_docstring(std::ofstream& out, t_struct* tstruct);
+  void generate_go_docstring(std::ostream& out, t_struct* tstruct);
 
-  void generate_go_docstring(std::ofstream& out, t_function* tfunction);
+  void generate_go_docstring(std::ostream& out, t_function* tfunction);
 
-  void generate_go_docstring(std::ofstream& out,
+  void generate_go_docstring(std::ostream& out,
                              t_doc* tdoc,
                              t_struct* tstruct,
                              const char* subheader);
 
-  void generate_go_docstring(std::ofstream& out, t_doc* tdoc);
+  void generate_go_docstring(std::ostream& out, t_doc* tdoc);
 
   /**
    * Helper rendering functions
@@ -287,16 +284,15 @@
   std::string gen_package_prefix_;
   std::string gen_thrift_import_;
   bool read_write_private_;
-  bool legacy_context_;
   bool ignore_initialisms_;
 
   /**
    * File streams
    */
 
-  std::ofstream f_types_;
+  ofstream_with_content_based_conditional_update f_types_;
   std::string f_types_name_;
-  std::ofstream f_consts_;
+  ofstream_with_content_based_conditional_update f_consts_;
   std::string f_consts_name_;
   std::stringstream f_const_values_;
 
@@ -381,7 +377,6 @@
   if (!(tfield->get_req() == t_field::T_OPTIONAL)) {
     return false;
   }
-
   bool has_default = tfield->get_value();
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -753,14 +748,6 @@
   f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go";
   f_consts_.open(f_consts_name_.c_str());
 
-  vector<t_service*> services = program_->get_services();
-  vector<t_service*>::iterator sv_iter;
-
-  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
-    string service_dir = package_dir_ + "/" + underscore((*sv_iter)->get_name()) + "-remote";
-    MKDIR(service_dir.c_str());
-  }
-
   // Print header
   f_types_ << go_autogen_comment() << go_package() << render_includes(false);
 
@@ -770,7 +757,7 @@
 
   // Create file for the GoUnusedProtection__ variable
   string f_unused_prot_name_ = package_dir_ + "/" + "GoUnusedProtection__.go";
-  ofstream f_unused_prot_;
+  ofstream_with_content_based_conditional_update f_unused_prot_;
   f_unused_prot_.open(f_unused_prot_name_.c_str());
   f_unused_prot_ << go_autogen_comment() << go_package() << render_import_protection();
   f_unused_prot_.close();
@@ -883,16 +870,10 @@
       "\t\"database/sql/driver\"\n"
       "\t\"errors\"\n";
   }
-  if (legacy_context_) {
-    extra +=
-      "\t\"golang.org/x/net/context\"\n";
-  } else {
-    extra +=
-      "\t\"context\"\n";
-  }
   return string(
       "import (\n"
       "\t\"bytes\"\n"
+      "\t\"context\"\n"
       "\t\"reflect\"\n"
       + extra +
       "\t\"fmt\"\n"
@@ -1052,7 +1033,6 @@
   t_type* type = tconst->get_type();
   string name = publicize(tconst->get_name());
   t_const_value* value = tconst->get_value();
-
   if (type->is_base_type() || type->is_enum()) {
     indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl;
   } else {
@@ -1068,45 +1048,96 @@
  * is NOT performed in this function as it is always run beforehand using the
  * validate_types method in main.cc
  */
-string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name) {
+string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name, bool opt) {
   type = get_true_type(type);
   std::ostringstream out;
 
   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:
-      if (type->is_binary()) {
-        out << "[]byte(\"" << get_escaped_string(value) << "\")";
-      } else {
-        out << '"' << get_escaped_string(value) << '"';
+    if (opt) {
+      out << "&(&struct{x ";
+      switch (tbase) {
+        case t_base_type::TYPE_BOOL:
+          out << "bool}{";
+          out << (value->get_integer() > 0 ? "true" : "false");
+          break;
+
+        case t_base_type::TYPE_I8:
+          out << "int8}{";
+          out << value->get_integer();
+          break;
+        case t_base_type::TYPE_I16:
+          out << "int16}{";
+          out << value->get_integer();
+          break;
+        case t_base_type::TYPE_I32:
+          out << "int32}{";
+          out << value->get_integer();
+          break;
+        case t_base_type::TYPE_I64:
+          out << "int64}{";
+          out << value->get_integer();
+          break;
+
+        case t_base_type::TYPE_DOUBLE:
+          out << "float64}{";
+          if (value->get_type() == t_const_value::CV_INTEGER) {
+            out << value->get_integer();
+          } else {
+            out << value->get_double();
+          }
+          break;
+
+        case t_base_type::TYPE_STRING:
+          out << "string}{";
+          out << '"' + get_escaped_string(value) + '"';
+          break;
+
+        default:
+          throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
       }
+      out << "}).x";
+    } else {
+      switch (tbase) {
+        case t_base_type::TYPE_STRING:
+          if (type->is_binary()) {
+            out << "[]byte(\"" << get_escaped_string(value) << "\")";
+          } else {
+            out << '"' << get_escaped_string(value) << '"';
+          }
 
-      break;
+          break;
 
-    case t_base_type::TYPE_BOOL:
-      out << (value->get_integer() > 0 ? "true" : "false");
-      break;
+        case t_base_type::TYPE_BOOL:
+          out << (value->get_integer() > 0 ? "true" : "false");
+          break;
 
-    case t_base_type::TYPE_I8:
-    case t_base_type::TYPE_I16:
-    case t_base_type::TYPE_I32:
-    case t_base_type::TYPE_I64:
-      out << value->get_integer();
-      break;
+        case t_base_type::TYPE_I8:
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+        case t_base_type::TYPE_I64:
+          if (opt) {
+            out << "&(&struct{x int}{";
+          }
+          out << value->get_integer();
+          if (opt) {
+            out << "}).x";
+          }
+          break;
 
-    case t_base_type::TYPE_DOUBLE:
-      if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
-      } else {
-        out << value->get_double();
+        case t_base_type::TYPE_DOUBLE:
+          if (value->get_type() == t_const_value::CV_INTEGER) {
+            out << value->get_integer();
+          } else {
+            out << value->get_double();
+          }
+
+          break;
+
+        default:
+          throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
       }
-
-      break;
-
-    default:
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
     }
   } else if (type->is_enum()) {
     indent(out) << value->get_integer();
@@ -1115,24 +1146,24 @@
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
-
+      bool is_optional = false;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
         if ((*f_iter)->get_name() == v_iter->first->get_string()) {
           field_type = (*f_iter)->get_type();
+          is_optional = is_pointer_field(*f_iter);
         }
       }
 
       if (field_type == NULL) {
         throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
       }
-
       out << endl << indent() << publicize(v_iter->first->get_string()) << ": "
-          << render_const_value(field_type, v_iter->second, name) << "," << endl;
+          << render_const_value(field_type, v_iter->second, name, is_optional) << "," << endl;
     }
 
     indent_down();
@@ -1141,10 +1172,10 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
     out << "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl;
     indent_up();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       out << indent() << render_const_value(ktype, v_iter->first, name) << ": "
@@ -1219,7 +1250,7 @@
   *OUT_def_value = tfield->get_value();
 }
 
-void t_go_generator::generate_go_struct_initializer(ofstream& out,
+void t_go_generator::generate_go_struct_initializer(ostream& out,
                                                     t_struct* tstruct,
                                                     bool is_args_or_result) {
   out << publicize(type_name(tstruct), is_args_or_result) << "{";
@@ -1245,7 +1276,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_go_generator::generate_go_struct_definition(ofstream& out,
+void t_go_generator::generate_go_struct_definition(ostream& out,
                                                    t_struct* tstruct,
                                                    bool is_exception,
                                                    bool is_result,
@@ -1292,7 +1323,7 @@
       if (tstruct->is_union())
         (*m_iter)->set_req(t_field::T_OPTIONAL);
       if (sorted_keys_pos != (*m_iter)->get_key()) {
-        int first_unused = std::max(1, sorted_keys_pos++);
+        int first_unused = (std::max)(1, sorted_keys_pos++);
         while (sorted_keys_pos != (*m_iter)->get_key()) {
           ++sorted_keys_pos;
         }
@@ -1356,6 +1387,14 @@
       }
       out << endl;
     }
+
+    // num_setable is used for deciding if Count* methods will be generated for union fields.
+    // This applies to all nullable fields including slices (used for set, list and binary) and maps, not just pointers.
+    t_type* type = fieldType->get_true_type();
+    if (is_pointer_field(*m_iter)|| type->is_map() || type->is_set() || type->is_list() || type->is_binary()) {
+      num_setable += 1;
+    }
+
     if (is_pointer_field(*m_iter)) {
       string goOptType = type_to_go_type_with_opt(fieldType, true);
       string maybepointer = goOptType != goType ? "*" : "";
@@ -1366,7 +1405,6 @@
       out << indent() << "  }" << endl;
       out << indent() << "return " << maybepointer << "p." << publicized_name << endl;
       out << indent() << "}" << endl;
-      num_setable += 1;
     } else {
       out << endl;
       out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "
@@ -1402,7 +1440,7 @@
 /**
  * Generates the IsSet helper methods for a struct
  */
-void t_go_generator::generate_isset_helpers(ofstream& out,
+void t_go_generator::generate_isset_helpers(ostream& out,
                                             t_struct* tstruct,
                                             const string& tstruct_name,
                                             bool is_result) {
@@ -1441,7 +1479,7 @@
 /**
  * Generates the CountSetFields helper method for a struct
  */
-void t_go_generator::generate_countsetfields_helper(ofstream& out,
+void t_go_generator::generate_countsetfields_helper(ostream& out,
                                                     t_struct* tstruct,
                                                     const string& tstruct_name,
                                                     bool is_result) {
@@ -1460,7 +1498,7 @@
 
     t_type* type = (*f_iter)->get_type()->get_true_type();
 
-    if (!(is_pointer_field(*f_iter) || type->is_map() || type->is_set() || type->is_list()))
+    if (!(is_pointer_field(*f_iter) || type->is_map() || type->is_set() || type->is_list() || type->is_binary()))
       continue;
 
     const string field_name(publicize(escape_string((*f_iter)->get_name())));
@@ -1480,7 +1518,7 @@
 /**
  * Generates the read method for a struct
  */
-void t_go_generator::generate_go_struct_reader(ofstream& out,
+void t_go_generator::generate_go_struct_reader(ostream& out,
                                                t_struct* tstruct,
                                                const string& tstruct_name,
                                                bool is_result) {
@@ -1553,17 +1591,19 @@
         << endl;
     out << indent() << "    return err" << endl;
     out << indent() << "  }" << endl;
+
+    // Mark required field as read
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      const string field_name(publicize(escape_string((*f_iter)->get_name())));
+      out << indent() << "  isset" << field_name << " = true" << endl;
+    }
+
     out << indent() << "} else {" << endl;
     out << indent() << "  if err := iprot.Skip(fieldTypeId); err != nil {" << endl;
     out << indent() << "    return err" << endl;
     out << indent() << "  }" << endl;
     out << indent() << "}" << endl;
 
-    // Mark required field as read
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
-      const string field_name(publicize(escape_string((*f_iter)->get_name())));
-      out << indent() << "isset" << field_name << " = true" << endl;
-    }
 
     indent_down();
   }
@@ -1633,7 +1673,7 @@
   }
 }
 
-void t_go_generator::generate_go_struct_writer(ofstream& out,
+void t_go_generator::generate_go_struct_writer(ostream& out,
                                                t_struct* tstruct,
                                                const string& tstruct_name,
                                                bool is_result,
@@ -1878,16 +1918,16 @@
   f_types_ << indent() << "type " << serviceName << "Client struct {" << endl;
   indent_up();
 
-  f_types_ << indent() << "c thrift.TClient" << endl;
   if (!extends_client.empty()) {
     f_types_ << indent() << "*" << extends_client << endl;
+  } else {
+    f_types_ << indent() << "c thrift.TClient" << endl;
   }
 
   indent_down();
   f_types_ << indent() << "}" << endl << endl;
 
   // Legacy constructor function
-  f_types_ << indent() << "// Deprecated: Use New" << serviceName << " instead" << endl;
   f_types_ << indent() << "func New" << serviceName
              << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName
              << "Client {" << endl;
@@ -1907,7 +1947,6 @@
   indent_down();
   f_types_ << indent() << "}" << endl << endl;
   // Legacy constructor function with custom input & output protocols
-  f_types_ << indent() << "// Deprecated: Use New" << serviceName << " instead" << endl;
   f_types_
       << indent() << "func New" << serviceName
       << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *"
@@ -1936,9 +1975,10 @@
   f_types_ << indent() << "return &" << serviceName << "Client{" << endl;
 
   indent_up();
-  f_types_ << indent() << "c: c," << endl;
   if (!extends.empty()) {
     f_types_ << indent() << extends_field << ": " << extends_client_new << "(c)," << endl;
+  } else {
+    f_types_ << indent() << "c: c," << endl;
   }
   indent_down();
   f_types_ << indent() << "}" << endl;
@@ -1946,6 +1986,14 @@
   indent_down();
   f_types_ << indent() << "}" << endl << endl;
 
+  if (extends.empty()) {
+    f_types_ << indent() << "func (p *" << serviceName << "Client) Client_() thrift.TClient {" << endl;
+    indent_up();
+    f_types_ << indent() << "return p.c" << endl;
+    indent_down();
+    f_types_ << indent() << "}" << endl;
+  }
+
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::const_iterator f_iter;
@@ -1975,7 +2023,7 @@
       std::string resultName = tmp("_result");
       std::string resultType = publicize(method + "_result", true);
       f_types_ << indent() << "var " << resultName << " " << resultType << endl;
-      f_types_ << indent() << "if err = p.c.Call(ctx, \""
+      f_types_ << indent() << "if err = p.Client_().Call(ctx, \""
         << method << "\", &" << argsName << ", &" << resultName << "); err != nil {" << endl;
 
       indent_up();
@@ -2016,7 +2064,7 @@
       }
     } else {
       // TODO: would be nice to not to duplicate the call generation
-      f_types_ << indent() << "if err := p.c.Call(ctx, \""
+      f_types_ << indent() << "if err := p.Client_().Call(ctx, \""
       << method << "\", &"<< argsName << ", nil); err != nil {" << endl;
 
       indent_up();
@@ -2047,10 +2095,18 @@
     parent = parent->get_extends();
   }
 
+  // This file is not useful if there are no functions; don't generate it
+  if (functions.size() == 0) {
+    return;
+  }
+
+  string f_remote_dir = package_dir_ + "/" + underscore(service_name_) + "-remote";
+  MKDIR(f_remote_dir.c_str());
+
   vector<t_function*>::iterator f_iter;
-  string f_remote_name = package_dir_ + "/" + underscore(service_name_) + "-remote/"
+  string f_remote_name = f_remote_dir + "/"
                          + underscore(service_name_) + "-remote.go";
-  ofstream f_remote;
+  ofstream_with_content_based_conditional_update f_remote;
   f_remote.open(f_remote_name.c_str());
   string service_module = get_real_go_module(program_);
   string::size_type loc;
@@ -2065,9 +2121,6 @@
   string unused_protection;
 
   string ctxPackage = "context";
-  if (legacy_context_) {
-    ctxPackage = "golang.org/x/net/context";
-  }
 
   f_remote << go_autogen_comment();
   f_remote << indent() << "package main" << endl << endl;
@@ -2100,7 +2153,6 @@
              << (*f_iter)->get_name() << "(";
     t_struct* arg_struct = (*f_iter)->get_arglist();
     const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
     std::vector<t_field*>::size_type num_args = args.size();
     bool first = true;
 
@@ -2121,6 +2173,24 @@
   f_remote << indent() << "  os.Exit(0)" << endl;
   f_remote << indent() << "}" << endl;
   f_remote << indent() << endl;
+
+  f_remote << indent() << "type httpHeaders map[string]string" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "func (h httpHeaders) String() string {" << endl;
+  f_remote << indent() << "  var m map[string]string = h" << endl;
+  f_remote << indent() << "  return fmt.Sprintf(\"%s\", m)" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << endl;
+  f_remote << indent() << "func (h httpHeaders) Set(value string) error {" << endl;
+  f_remote << indent() << "  parts := strings.Split(value, \": \")" << endl;
+  f_remote << indent() << "  if len(parts) != 2 {" << endl;
+  f_remote << indent() << "    return fmt.Errorf(\"header should be of format 'Key: Value'\")" << endl;
+  f_remote << indent() << "  }" << endl;
+  f_remote << indent() << "  h[parts[0]] = parts[1]" << endl;
+  f_remote << indent() << "  return nil" << endl;
+  f_remote << indent() << "}" << endl;
+  f_remote << indent() << endl;
+
   f_remote << indent() << "func main() {" << endl;
   indent_up();
   f_remote << indent() << "flag.Usage = Usage" << endl;
@@ -2130,6 +2200,7 @@
   f_remote << indent() << "var urlString string" << endl;
   f_remote << indent() << "var framed bool" << endl;
   f_remote << indent() << "var useHttp bool" << endl;
+  f_remote << indent() << "headers := make(httpHeaders)" << endl;
   f_remote << indent() << "var parsedUrl *url.URL" << endl;
   f_remote << indent() << "var trans thrift.TTransport" << endl;
   f_remote << indent() << "_ = strconv.Atoi" << endl;
@@ -2144,6 +2215,7 @@
   f_remote << indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")"
            << endl;
   f_remote << indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl;
+  f_remote << indent() << "flag.Var(headers, \"H\", \"Headers to set on the http(s) request (e.g. -H \\\"Key: Value\\\")\")" << endl;
   f_remote << indent() << "flag.Parse()" << endl;
   f_remote << indent() << endl;
   f_remote << indent() << "if len(urlString) > 0 {" << endl;
@@ -2154,7 +2226,7 @@
   f_remote << indent() << "    flag.Usage()" << endl;
   f_remote << indent() << "  }" << endl;
   f_remote << indent() << "  host = parsedUrl.Host" << endl;
-  f_remote << indent() << "  useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\""
+  f_remote << indent() << "  useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\" || parsedUrl.Scheme == \"https\""
            << endl;
   f_remote << indent() << "} else if useHttp {" << endl;
   f_remote << indent() << "  _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))"
@@ -2169,6 +2241,12 @@
   f_remote << indent() << "var err error" << endl;
   f_remote << indent() << "if useHttp {" << endl;
   f_remote << indent() << "  trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl;
+  f_remote << indent() << "  if len(headers) > 0 {" << endl;
+  f_remote << indent() << "    httptrans := trans.(*thrift.THttpClient)" << endl;
+  f_remote << indent() << "    for key, value := range headers {" << endl;
+  f_remote << indent() << "      httptrans.SetHeader(key, value)" << endl;
+  f_remote << indent() << "    }" << endl;
+  f_remote << indent() << "  }" << endl;
   f_remote << indent() << "} else {" << endl;
   f_remote << indent() << "  portStr := fmt.Sprint(port)" << endl;
   f_remote << indent() << "  if strings.Contains(host, \":\") {" << endl;
@@ -2229,7 +2307,6 @@
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     t_struct* arg_struct = (*f_iter)->get_arglist();
     const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
     std::vector<t_field*>::size_type num_args = args.size();
     string funcName((*f_iter)->get_name());
     string pubName(publicize(funcName));
@@ -2355,7 +2432,7 @@
         f_remote << indent() << "  Usage()" << endl;
         f_remote << indent() << "  return" << endl;
         f_remote << indent() << "}" << endl;
-        f_remote << indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl;
+        f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl;
         f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")"
                  << endl;
         f_remote << indent() << "argvalue" << i << " := " << tstruct_module << ".New" << tstruct_name
@@ -2383,7 +2460,7 @@
         f_remote << indent() << "  Usage()" << endl;
         f_remote << indent() << "  return" << endl;
         f_remote << indent() << "}" << endl;
-        f_remote << indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl;
+        f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl;
         f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")"
                  << endl;
         f_remote << indent() << "containerStruct" << i << " := " << package_name_ << ".New"
@@ -2568,7 +2645,7 @@
     f_types_ << indent() << "  oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)" << endl;
     f_types_ << indent() << "  " << x << ".Write(oprot)" << endl;
     f_types_ << indent() << "  oprot.WriteMessageEnd()" << endl;
-    f_types_ << indent() << "  oprot.Flush()" << endl;
+    f_types_ << indent() << "  oprot.Flush(ctx)" << endl;
     f_types_ << indent() << "  return false, " << x << endl;
     f_types_ << indent() << "" << endl;
     f_types_ << indent() << "}" << endl << endl;
@@ -2614,7 +2691,6 @@
 
   // t_struct* xs = tfunction->get_xceptions();
   // const std::vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
   f_types_ << indent() << "type " << processorName << " struct {" << endl;
   f_types_ << indent() << "  handler " << publicize(tservice->get_name()) << endl;
   f_types_ << indent() << "}" << endl << endl;
@@ -2633,7 +2709,7 @@
                << "\", thrift.EXCEPTION, seqId)" << endl;
     f_types_ << indent() << "  x.Write(oprot)" << endl;
     f_types_ << indent() << "  oprot.WriteMessageEnd()" << endl;
-    f_types_ << indent() << "  oprot.Flush()" << endl;
+    f_types_ << indent() << "  oprot.Flush(ctx)" << endl;
   }
   f_types_ << indent() << "  return false, err" << endl;
   f_types_ << indent() << "}" << endl << endl;
@@ -2701,7 +2777,7 @@
                << "\", thrift.EXCEPTION, seqId)" << endl;
     f_types_ << indent() << "  x.Write(oprot)" << endl;
     f_types_ << indent() << "  oprot.WriteMessageEnd()" << endl;
-    f_types_ << indent() << "  oprot.Flush()" << endl;
+    f_types_ << indent() << "  oprot.Flush(ctx)" << endl;
   }
 
   f_types_ << indent() << "  return true, err2" << endl;
@@ -2738,7 +2814,7 @@
                << endl;
     f_types_ << indent() << "  err = err2" << endl;
     f_types_ << indent() << "}" << endl;
-    f_types_ << indent() << "if err2 = oprot.Flush(); err == nil && err2 != nil {" << endl;
+    f_types_ << indent() << "if err2 = oprot.Flush(ctx); err == nil && err2 != nil {" << endl;
     f_types_ << indent() << "  err = err2" << endl;
     f_types_ << indent() << "}" << endl;
     f_types_ << indent() << "if err != nil {" << endl;
@@ -2756,7 +2832,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_go_generator::generate_deserialize_field(ofstream& out,
+void t_go_generator::generate_deserialize_field(ostream& out,
                                                 t_field* tfield,
                                                 bool declare,
                                                 string prefix,
@@ -2872,7 +2948,7 @@
 /**
  * Generates an unserializer for a struct, calling read()
  */
-void t_go_generator::generate_deserialize_struct(ofstream& out,
+void t_go_generator::generate_deserialize_struct(ostream& out,
                                                  t_struct* tstruct,
                                                  bool pointer_field,
                                                  bool declare,
@@ -2891,7 +2967,7 @@
  * Serialize a container by writing out the header followed by
  * data and then a footer.
  */
-void t_go_generator::generate_deserialize_container(ofstream& out,
+void t_go_generator::generate_deserialize_container(ostream& out,
                                                     t_type* orig_type,
                                                     bool pointer_field,
                                                     bool declare,
@@ -2967,7 +3043,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_go_generator::generate_deserialize_map_element(ofstream& out,
+void t_go_generator::generate_deserialize_map_element(ostream& out,
                                                       t_map* tmap,
                                                       bool declare,
                                                       string prefix) {
@@ -2986,7 +3062,7 @@
 /**
  * Write a set element
  */
-void t_go_generator::generate_deserialize_set_element(ofstream& out,
+void t_go_generator::generate_deserialize_set_element(ostream& out,
                                                       t_set* tset,
                                                       bool declare,
                                                       string prefix) {
@@ -3001,7 +3077,7 @@
 /**
  * Write a list element
  */
-void t_go_generator::generate_deserialize_list_element(ofstream& out,
+void t_go_generator::generate_deserialize_list_element(ostream& out,
                                                        t_list* tlist,
                                                        bool declare,
                                                        string prefix) {
@@ -3019,7 +3095,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_go_generator::generate_serialize_field(ofstream& out,
+void t_go_generator::generate_serialize_field(ostream& out,
                                               t_field* tfield,
                                               string prefix,
                                               bool inkey) {
@@ -3106,7 +3182,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_go_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_go_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   out << indent() << "if err := " << prefix << "." << write_method_name_ << "(oprot); err != nil {" << endl;
   out << indent() << "  return thrift.PrependError(fmt.Sprintf(\"%T error writing struct: \", "
@@ -3114,7 +3190,7 @@
   out << indent() << "}" << endl;
 }
 
-void t_go_generator::generate_serialize_container(ofstream& out,
+void t_go_generator::generate_serialize_container(ostream& out,
                                                   t_type* ttype,
                                                   bool pointer_field,
                                                   string prefix) {
@@ -3195,7 +3271,7 @@
  * Serializes the members of a map.
  *
  */
-void t_go_generator::generate_serialize_map_element(ofstream& out,
+void t_go_generator::generate_serialize_map_element(ostream& out,
                                                     t_map* tmap,
                                                     string kiter,
                                                     string viter) {
@@ -3210,7 +3286,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_go_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_go_generator::generate_serialize_set_element(ostream& out, t_set* tset, string prefix) {
   t_field efield(tset->get_elem_type(), "");
   efield.set_req(t_field::T_OPT_IN_REQ_OUT);
   generate_serialize_field(out, &efield, prefix);
@@ -3219,7 +3295,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_go_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string prefix) {
+void t_go_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string prefix) {
   t_field efield(tlist->get_elem_type(), "");
   efield.set_req(t_field::T_OPT_IN_REQ_OUT);
   generate_serialize_field(out, &efield, prefix);
@@ -3228,21 +3304,21 @@
 /**
  * Generates the docstring for a given struct.
  */
-void t_go_generator::generate_go_docstring(ofstream& out, t_struct* tstruct) {
+void t_go_generator::generate_go_docstring(ostream& out, t_struct* tstruct) {
   generate_go_docstring(out, tstruct, tstruct, "Attributes");
 }
 
 /**
  * Generates the docstring for a given function.
  */
-void t_go_generator::generate_go_docstring(ofstream& out, t_function* tfunction) {
+void t_go_generator::generate_go_docstring(ostream& out, t_function* tfunction) {
   generate_go_docstring(out, tfunction, tfunction->get_arglist(), "Parameters");
 }
 
 /**
  * Generates the docstring for a struct or function.
  */
-void t_go_generator::generate_go_docstring(ofstream& out,
+void t_go_generator::generate_go_docstring(ostream& out,
                                            t_doc* tdoc,
                                            t_struct* tstruct,
                                            const char* subheader) {
@@ -3285,7 +3361,7 @@
 /**
  * Generates the docstring for a generic object.
  */
-void t_go_generator::generate_go_docstring(ofstream& out, t_doc* tdoc) {
+void t_go_generator::generate_go_docstring(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_docstring_comment(out, "", "//", tdoc->get_doc(), "");
   }
@@ -3634,6 +3710,4 @@
                           "    ignore_initialisms\n"
                           "                     Disable automatic spelling correction of initialisms (e.g. \"URL\")\n" \
                           "    read_write_private\n"
-                          "                     Make read/write methods private, default is public Read/Write\n" \
-                          "    legacy_context\n"
-                          "                     Use legacy x/net/context instead of context in go<1.7.\n")
+                          "                     Make read/write methods private, default is public Read/Write\n")
diff --git a/compiler/cpp/src/thrift/generate/t_gv_generator.cc b/compiler/cpp/src/thrift/generate/t_gv_generator.cc
index 14b5377..7f8301a 100644
--- a/compiler/cpp/src/thrift/generate/t_gv_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_gv_generator.cc
@@ -87,7 +87,7 @@
   void print_const_value(t_type* type, t_const_value* tvalue);
 
 private:
-  std::ofstream f_out_;
+  ofstream_with_content_based_conditional_update f_out_;
   std::list<string> edges;
   bool exception_arrows;
 };
@@ -249,8 +249,8 @@
     break;
   case t_const_value::CV_MAP: {
     f_out_ << "\\{ ";
-    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::iterator map_iter;
+    map<t_const_value*, t_const_value*, t_const_value::value_compare> map_elems = tvalue->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::iterator map_iter;
     for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
       if (!first) {
         f_out_ << ", ";
diff --git a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
index 97c7d19..3b88c4d 100644
--- a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc
@@ -31,7 +31,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -89,13 +89,13 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false);
-  std::string render_const_value(ofstream& out,
+  std::string render_const_value(ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
@@ -106,18 +106,18 @@
 
   void generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result = false);
 
-  void generate_haxe_struct_definition(std::ofstream& out,
+  void generate_haxe_struct_definition(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false,
                                        bool is_result = false);
   // removed -- equality,compare_to
-  void generate_haxe_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_haxe_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  void generate_haxe_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_haxe_validator(std::ostream& out, t_struct* tstruct);
+  void generate_haxe_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_haxe_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_haxe_struct_tostring(std::ostream& out, t_struct* tstruct);
+  void generate_haxe_meta_data_map(std::ostream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ostream& out, t_type* type);
   std::string get_haxe_type_string(t_type* type);
   void generate_reflection_setters(std::ostringstream& out,
                                    t_type* type,
@@ -127,15 +127,15 @@
                                    t_type* type,
                                    std::string field_name,
                                    std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_property_getters_setters(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct);
+  void generate_property_getters_setters(std::ostream& out, t_struct* tstruct);
 
   void generate_function_helpers(t_function* tfunction);
   std::string get_cap_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
+  void generate_isset_set(ostream& out, t_field* field);
   // removed std::string isset_field_id(t_field* field);
 
   void generate_service_interface(t_service* tservice);
@@ -149,30 +149,30 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
 
-  void generate_haxe_doc(std::ofstream& out, t_doc* tdoc);
-  void generate_haxe_doc(std::ofstream& out, t_function* tdoc);
+  void generate_haxe_doc(std::ostream& out, t_doc* tdoc);
+  void generate_haxe_doc(std::ostream& out, t_function* tdoc);
 
-  void generate_rtti_decoration(std::ofstream& out);
-  void generate_macro_decoration(std::ofstream& out);
+  void generate_rtti_decoration(std::ostream& out);
+  void generate_macro_decoration(std::ostream& out);
 
   /**
    * Helper rendering functions
@@ -229,7 +229,7 @@
    */
 
   std::string package_name_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
   std::string package_dir_;
 };
 
@@ -386,7 +386,7 @@
 void t_haxe_generator::generate_enum(t_enum* tenum) {
   // Make output file
   string f_enum_name = package_dir_ + "/" + get_cap_name(tenum->get_name()) + ".hx";
-  ofstream f_enum;
+  ofstream_with_content_based_conditional_update f_enum;
   f_enum.open(f_enum_name.c_str());
 
   // Comment and package it
@@ -448,7 +448,7 @@
   }
 
   string f_consts_name = package_dir_ + "/" + get_cap_name(program_name_) + "Constants.hx";
-  ofstream f_consts;
+  ofstream_with_content_based_conditional_update f_consts;
   f_consts.open(f_consts_name.c_str());
 
   // Print header
@@ -475,7 +475,7 @@
   f_consts.close();
 }
 
-void t_haxe_generator::print_const_value(std::ofstream& out,
+void t_haxe_generator::print_const_value(std::ostream& out,
                                          string name,
                                          t_type* type,
                                          t_const_value* value,
@@ -503,8 +503,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
         << endl;
     if (!in_static) {
@@ -548,8 +548,8 @@
     }
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
       string val = render_const_value(out, name, vtype, v_iter->second);
@@ -599,7 +599,7 @@
   }
 }
 
-string t_haxe_generator::render_const_value(ofstream& out,
+string t_haxe_generator::render_const_value(ostream& out,
                                             string name,
                                             t_type* type,
                                             t_const_value* value) {
@@ -676,7 +676,7 @@
 void t_haxe_generator::generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result) {
   // Make output file
   string f_struct_name = package_dir_ + "/" + get_cap_name(tstruct->get_name()) + ".hx";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << haxe_package() << ";" << endl;
@@ -703,7 +703,7 @@
  * @param in_class     If inside a class, needs to be static class
  * @param is_result    If this is a result it needs a different writer
  */
-void t_haxe_generator::generate_haxe_struct_definition(ofstream& out,
+void t_haxe_generator::generate_haxe_struct_definition(ostream& out,
                                                        t_struct* tstruct,
                                                        bool is_exception,
                                                        bool is_result) {
@@ -817,7 +817,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_haxe_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_struct_reader(ostream& out, t_struct* tstruct) {
   out << indent() << "public function read( iprot : TProtocol) : Void {" << endl;
   indent_up();
 
@@ -910,7 +910,7 @@
 
 // generates haxe method to perform various checks
 // (e.g. check that all required fields are set)
-void t_haxe_generator::generate_haxe_validator(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "public function validate() : Void {" << endl;
   indent_up();
 
@@ -961,7 +961,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_haxe_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
   indent_up();
 
@@ -1031,7 +1031,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_haxe_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_struct_result_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public function write(oprot:TProtocol) : Void {" << endl;
   indent_up();
 
@@ -1116,7 +1116,7 @@
   indent_down();
 }
 
-void t_haxe_generator::generate_generic_field_getters_setters(std::ofstream& out,
+void t_haxe_generator::generate_generic_field_getters_setters(std::ostream& out,
                                                               t_struct* tstruct) {
 
   std::ostringstream getter_stream;
@@ -1174,7 +1174,7 @@
 }
 
 // Creates a generic isSet method that takes the field number as argument
-void t_haxe_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -1210,7 +1210,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_property_getters_setters(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_property_getters_setters(ostream& out, t_struct* tstruct) {
   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) {
@@ -1272,7 +1272,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_haxe_struct_tostring(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_struct_tostring(ostream& out, t_struct* tstruct) {
   out << indent() << "public "
       << "function toString() : String {" << endl;
   indent_up();
@@ -1346,7 +1346,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_haxe_generator::generate_haxe_meta_data_map(ofstream& out, t_struct* tstruct) {
+void t_haxe_generator::generate_haxe_meta_data_map(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -1434,7 +1434,7 @@
   }
 }
 
-void t_haxe_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+void t_haxe_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) {
   out << endl;
   indent_up();
   indent_up();
@@ -2176,7 +2176,7 @@
  * @param tfield The field
  * @param prefix The variable name or container for this field
  */
-void t_haxe_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_haxe_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   if (type->is_void()) {
@@ -2241,7 +2241,7 @@
 /**
  * Generates an unserializer for a struct, invokes read()
  */
-void t_haxe_generator::generate_deserialize_struct(ofstream& out,
+void t_haxe_generator::generate_deserialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix) {
   out << indent() << prefix << " = new " << get_cap_name(type_name(tstruct)) << "();" << endl
@@ -2251,7 +2251,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_haxe_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_haxe_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   string obj;
@@ -2309,7 +2309,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_haxe_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_haxe_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
@@ -2327,7 +2327,7 @@
 /**
  * Deserializes a set element
  */
-void t_haxe_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_haxe_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -2341,7 +2341,7 @@
 /**
  * Deserializes a list element
  */
-void t_haxe_generator::generate_deserialize_list_element(ofstream& out,
+void t_haxe_generator::generate_deserialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string prefix) {
   string elem = tmp("_elem");
@@ -2360,7 +2360,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_haxe_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_haxe_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2429,7 +2429,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_haxe_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_haxe_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   out << indent() << prefix << ".write(oprot);" << endl;
 }
@@ -2440,7 +2440,7 @@
  * @param ttype  The type of container
  * @param prefix String prefix for fields
  */
-void t_haxe_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_haxe_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -2498,7 +2498,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_haxe_generator::generate_serialize_map_element(ofstream& out,
+void t_haxe_generator::generate_serialize_map_element(ostream& out,
                                                       t_map* tmap,
                                                       string iter,
                                                       string map) {
@@ -2511,7 +2511,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_haxe_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_haxe_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2519,7 +2519,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_haxe_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_haxe_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2661,7 +2661,7 @@
   if (init) {
     t_type* ttype = get_true_type(tfield->get_type());
     if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
+      std::ofstream dummy;
       result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -2904,7 +2904,7 @@
 /**
  * Enables RTTI for a class or interface
  */
-void t_haxe_generator::generate_rtti_decoration(ofstream& out) {
+void t_haxe_generator::generate_rtti_decoration(ostream& out) {
   if (rtti_) {
     out << "@:rtti" << endl;
   }
@@ -2913,7 +2913,7 @@
 /**
  * Adds build macros to a class or interface
  */
-void t_haxe_generator::generate_macro_decoration(ofstream& out) {
+void t_haxe_generator::generate_macro_decoration(ostream& out) {
   if (!buildmacro_.empty()) {
     out << "#if ! macro" << endl;
     out << "@:build( " << buildmacro_ << ")" << endl;     // current class/interface
@@ -2925,7 +2925,7 @@
 /**
  * Emits a haxeDoc comment if the provided object has a doc in Thrift
  */
-void t_haxe_generator::generate_haxe_doc(ofstream& out, t_doc* tdoc) {
+void t_haxe_generator::generate_haxe_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n");
   }
@@ -2934,7 +2934,7 @@
 /**
  * Emits a haxeDoc comment if the provided function object has a doc in Thrift
  */
-void t_haxe_generator::generate_haxe_doc(ofstream& out, t_function* tfunction) {
+void t_haxe_generator::generate_haxe_doc(ostream& out, t_function* tfunction) {
   if (tfunction->has_doc()) {
     stringstream ss;
     ss << tfunction->get_doc();
@@ -2959,7 +2959,7 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_haxe_generator::generate_isset_set(ofstream& out, t_field* field) {
+void t_haxe_generator::generate_isset_set(ostream& out, t_field* field) {
   if (!type_can_be_null(field->get_type())) {
     indent(out) << "this.__isset_" << field->get_name() << " = true;" << endl;
   }
diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc
index d0a8cb2..8f6d4b0 100644
--- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc
@@ -33,7 +33,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -87,22 +87,22 @@
 
   void generate_hs_struct(t_struct* tstruct, bool is_exception);
 
-  void generate_hs_struct_definition(ofstream& out,
+  void generate_hs_struct_definition(ostream& out,
                                      t_struct* tstruct,
                                      bool is_xception = false,
                                      bool helper = false);
 
-  void generate_hs_struct_reader(ofstream& out, t_struct* tstruct);
+  void generate_hs_struct_reader(ostream& out, t_struct* tstruct);
 
-  void generate_hs_struct_writer(ofstream& out, t_struct* tstruct);
+  void generate_hs_struct_writer(ostream& out, t_struct* tstruct);
 
-  void generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct);
+  void generate_hs_struct_arbitrary(ostream& out, t_struct* tstruct);
 
   void generate_hs_function_helpers(t_function* tfunction);
 
-  void generate_hs_typemap(ofstream& out, t_struct* tstruct);
+  void generate_hs_typemap(ostream& out, t_struct* tstruct);
 
-  void generate_hs_default(ofstream& out, t_struct* tstruct);
+  void generate_hs_default(ostream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
@@ -118,29 +118,29 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(ofstream& out, t_field* tfield, string prefix);
+  void generate_deserialize_field(ostream& out, t_field* tfield, string prefix);
 
-  void generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name = "");
+  void generate_deserialize_struct(ostream& out, t_struct* tstruct, string name = "");
 
-  void generate_deserialize_container(ofstream& out, t_type* ttype, string arg = "");
+  void generate_deserialize_container(ostream& out, t_type* ttype, string arg = "");
 
-  void generate_deserialize_set_element(ofstream& out, t_set* tset);
+  void generate_deserialize_set_element(ostream& out, t_set* tset);
 
-  void generate_deserialize_list_element(ofstream& out, t_list* tlist, string prefix = "");
+  void generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix = "");
 
-  void generate_deserialize_type(ofstream& out, t_type* type, string arg = "");
+  void generate_deserialize_type(ostream& out, t_type* type, string arg = "");
 
-  void generate_serialize_type(ofstream& out, t_type* type, string name = "");
+  void generate_serialize_type(ostream& out, t_type* type, string name = "");
 
-  void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix = "");
+  void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix = "");
 
-  void generate_serialize_container(ofstream& out, t_type* ttype, string prefix = "");
+  void generate_serialize_container(ostream& out, t_type* ttype, string prefix = "");
 
-  void generate_serialize_map_element(ofstream& out, t_map* tmap, string kiter, string viter);
+  void generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter);
 
-  void generate_serialize_set_element(ofstream& out, t_set* tmap, string iter);
+  void generate_serialize_set_element(ostream& out, t_set* tmap, string iter);
 
-  void generate_serialize_list_element(ofstream& out, t_list* tlist, string iter);
+  void generate_serialize_list_element(ostream& out, t_list* tlist, string iter);
 
   /**
    * Helper rendering functions
@@ -170,11 +170,11 @@
   string render_hs_type_for_function_name(t_type* type);
 
 private:
-  ofstream f_types_;
-  ofstream f_consts_;
-  ofstream f_service_;
-  ofstream f_iface_;
-  ofstream f_client_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_consts_;
+  ofstream_with_content_based_conditional_update f_service_;
+  ofstream_with_content_based_conditional_update f_iface_;
+  ofstream_with_content_based_conditional_update f_client_;
 };
 
 /**
@@ -424,10 +424,10 @@
     out << "default_" << cname << "{";
 
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
 
     bool first = true;
-    for (map<t_const_value*, t_const_value*>::const_iterator v_iter = val.begin();
+    for (map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter = val.begin();
          v_iter != val.end();
          ++v_iter) {
       t_field* field = NULL;
@@ -458,8 +458,8 @@
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     out << "(Map.fromList [";
 
@@ -530,7 +530,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_hs_generator::generate_hs_struct_definition(ofstream& out,
+void t_hs_generator::generate_hs_struct_definition(ostream& out,
                                                    t_struct* tstruct,
                                                    bool is_exception,
                                                    bool helper) {
@@ -586,11 +586,10 @@
   generate_hs_default(out, tstruct);
 }
 
-void t_hs_generator::generate_hs_struct_arbitrary(ofstream& out, t_struct* tstruct) {
+void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruct) {
   string tname = type_name(tstruct);
   string name = tstruct->get_name();
   const vector<t_field*>& members = tstruct->get_members();
-  vector<t_field*>::const_iterator m_iter;
 
   indent(out) << "instance QC.Arbitrary " << tname << " where " << endl;
   indent_up();
@@ -652,9 +651,8 @@
 /**
  * Generates the read method for a struct
  */
-void t_hs_generator::generate_hs_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
 
   string sname = type_name(tstruct);
   string id = tmp("_id");
@@ -722,10 +720,9 @@
   out << "T.deserializeVal iprot (T.T_STRUCT " << tmap << ") bs" << endl;
 }
 
-void t_hs_generator::generate_hs_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) {
   string name = type_name(tstruct);
   const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
   string str = tmp("_str");
   string f = tmp("_f");
   string v = tmp("_v");
@@ -906,10 +903,9 @@
  * Generate the map from field names to (type, id)
  * @param tstruct the Struct
  */
-void t_hs_generator::generate_hs_typemap(ofstream& out, t_struct* tstruct) {
+void t_hs_generator::generate_hs_typemap(ostream& out, t_struct* tstruct) {
   string name = type_name(tstruct);
   const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
 
   indent(out) << "typemap_" << name << " :: T.TypeMap" << endl;
   indent(out) << "typemap_" << name << " = Map.fromList [";
@@ -932,7 +928,7 @@
  * generate the struct with default values filled in
  * @param tstruct the Struct
  */
-void t_hs_generator::generate_hs_default(ofstream& out, t_struct* tstruct) {
+void t_hs_generator::generate_hs_default(ostream& out, t_struct* tstruct) {
   string name = type_name(tstruct);
   string fname = type_name(tstruct, "default_");
   const vector<t_field*>& fields = tstruct->get_sorted_members();
@@ -1342,7 +1338,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_hs_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_hs_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   (void)prefix;
   t_type* type = tfield->get_type();
   generate_deserialize_type(out, type, prefix);
@@ -1351,7 +1347,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_hs_generator::generate_deserialize_type(ofstream& out, t_type* type, string arg) {
+void t_hs_generator::generate_deserialize_type(ostream& out, t_type* type, string arg) {
   type = get_true_type(type);
   string val = tmp("_val");
   out << "(case " << arg << " of {" << type_to_constructor(type) << " " << val << " -> ";
@@ -1388,7 +1384,7 @@
 /**
  * Generates an unserializer for a struct, calling read()
  */
-void t_hs_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string name) {
+void t_hs_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string name) {
 
   out << "(" << type_name(tstruct, "to_") << " (T.TStruct " << name << "))";
 }
@@ -1397,7 +1393,7 @@
  * Serialize a container by writing out the header followed by
  * data and then a footer.
  */
-void t_hs_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string arg) {
+void t_hs_generator::generate_deserialize_container(ostream& out, t_type* ttype, string arg) {
 
   string val = tmp("_v");
   // Declare variables, read header
@@ -1429,7 +1425,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_hs_generator::generate_serialize_type(ofstream& out, t_type* type, string name) {
+void t_hs_generator::generate_serialize_type(ostream& out, t_type* type, string name) {
 
   type = get_true_type(type);
   // Do nothing for void types
@@ -1467,11 +1463,11 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_hs_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_hs_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   out << type_name(tstruct, "from_") << " " << prefix;
 }
 
-void t_hs_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_hs_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   string k = tmp("_k");
   string v = tmp("_v");
 
diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.cc b/compiler/cpp/src/thrift/generate/t_html_generator.cc
index dfd5df3..8dfa389 100644
--- a/compiler/cpp/src/thrift/generate/t_html_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_html_generator.cc
@@ -90,7 +90,7 @@
   std::string escape_html(std::string const& str);
   std::string escape_html_tags(std::string const& str);
   void generate_css();
-  void generate_css_content(std::ofstream& f_target);
+  void generate_css_content(std::ostream& f_target);
   void generate_style_tag();
   std::string make_file_link(std::string name);
   bool is_utf8_sequence(std::string const& str, size_t firstpos);
@@ -114,7 +114,7 @@
   void print_fn_args_doc(t_function* tfunction);
 
 private:
-  std::ofstream f_out_;
+  ofstream_with_content_based_conditional_update f_out_;
   std::string current_file_;
   input_type input_type_;
   std::map<std::string, int> allowed_markup;
@@ -359,7 +359,7 @@
   }
 }
 
-void t_html_generator::generate_css_content(std::ofstream& f_target) {
+void t_html_generator::generate_css_content(std::ostream& f_target) {
   f_target << BOOTSTRAP_CSS() << endl;
   f_target << "/* Auto-generated CSS for generated Thrift docs */" << endl;
   f_target << "h3, h4 { margin-bottom: 6px; }" << endl;
@@ -777,8 +777,8 @@
     f_out_ << "{ ";
     const vector<t_field*>& fields = ((t_struct*)truetype)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = tvalue->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -800,8 +800,8 @@
     f_out_ << " }";
   } else if (truetype->is_map()) {
     f_out_ << "{ ";
-    map<t_const_value*, t_const_value*> map_elems = tvalue->get_map();
-    map<t_const_value*, t_const_value*>::iterator map_iter;
+    map<t_const_value*, t_const_value*, t_const_value::value_compare> map_elems = tvalue->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::iterator map_iter;
     for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) {
       if (!first) {
         f_out_ << ", ";
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc
index ebc8350..2c84551 100644
--- a/compiler/cpp/src/thrift/generate/t_java_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc
@@ -25,6 +25,7 @@
 #include <fstream>
 #include <iomanip>
 #include <iostream>
+#include <limits>
 #include <vector>
 #include <cctype>
 
@@ -35,7 +36,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::setfill;
 using std::setw;
@@ -70,7 +71,8 @@
     use_option_type_ = false;
     undated_generated_annotations_  = false;
     suppress_generated_annotations_ = false;
-    handle_runtime_exceptions_ = false;
+    rethrow_unhandled_exceptions_ = false;
+    unsafe_binaries_ = false;
     for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if( iter->first.compare("beans") == 0) {
         bean_style_ = true;
@@ -92,8 +94,8 @@
         reuse_objects_ = true;
       } else if( iter->first.compare("option_type") == 0) {
         use_option_type_ = true;
-      } else if( iter->first.compare("handle_runtime_exceptions") == 0) {
-        handle_runtime_exceptions_ = true;
+      } else if( iter->first.compare("rethrow_unhandled_exceptions") == 0) {
+        rethrow_unhandled_exceptions_ = true;
       } else if( iter->first.compare("generated_annotations") == 0) {
         if( iter->second.compare("undated") == 0) {
           undated_generated_annotations_  = true;
@@ -102,6 +104,8 @@
         } else {
           throw "unknown option java:" + iter->first + "=" + iter->second;
         }
+      } else if( iter->first.compare("unsafe_binaries") == 0) {
+        unsafe_binaries_ = true;
       } else {
         throw "unknown option java:" + iter->first;
       }
@@ -134,13 +138,13 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false);
-  std::string render_const_value(std::ofstream& out, t_type* type, t_const_value* value);
+  std::string render_const_value(std::ostream& out, t_type* type, t_const_value* value);
 
   /**
    * Service-level generation functions
@@ -148,26 +152,26 @@
 
   void generate_java_struct(t_struct* tstruct, bool is_exception);
 
-  void generate_java_struct_definition(std::ofstream& out,
+  void generate_java_struct_definition(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false,
                                        bool in_class = false,
                                        bool is_result = false);
-  void generate_java_struct_parcelable(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_write_object(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_read_object(std::ofstream& out, t_struct* tstruct);
-  void generate_java_meta_data_map(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  void generate_java_struct_parcelable(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_equality(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_compare_to(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_java_validator(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_tostring(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_clear(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_write_object(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_read_object(std::ostream& out, t_struct* tstruct);
+  void generate_java_meta_data_map(std::ostream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ostream& out, t_type* type);
   std::string get_java_type_string(t_type* type);
-  void generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_field_by_id(ostream& out, t_struct* tstruct);
   void generate_reflection_setters(std::ostringstream& out,
                                    t_type* type,
                                    std::string field_name,
@@ -176,9 +180,9 @@
                                    t_type* type,
                                    std::string field_name,
                                    std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
-  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct);
+  void generate_java_bean_boilerplate(std::ostream& out, t_struct* tstruct);
 
   void generate_function_helpers(t_function* tfunction);
   std::string as_camel_case(std::string name, bool ucfirst = true);
@@ -186,7 +190,7 @@
   std::string get_cap_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field, std::string prefix);
+  void generate_isset_set(ostream& out, t_field* field, std::string prefix);
   std::string isset_field_id(t_field* field);
 
   void generate_service_interface(t_service* tservice);
@@ -200,102 +204,102 @@
   void generate_process_async_function(t_service* tservice, t_function* tfunction);
 
   void generate_java_union(t_struct* tstruct);
-  void generate_union_constructor(ofstream& out, t_struct* tstruct);
-  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
-  void generate_union_is_set_methods(ofstream& out, t_struct* tstruct);
-  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
-  void generate_check_type(ofstream& out, t_struct* tstruct);
-  void generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct);
-  void generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct);
-  void generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct);
-  void generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct);
-  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_field_name(ofstream& out, t_struct* tstruct);
+  void generate_union_constructor(ostream& out, t_struct* tstruct);
+  void generate_union_getters_and_setters(ostream& out, t_struct* tstruct);
+  void generate_union_is_set_methods(ostream& out, t_struct* tstruct);
+  void generate_union_abstract_methods(ostream& out, t_struct* tstruct);
+  void generate_check_type(ostream& out, t_struct* tstruct);
+  void generate_standard_scheme_read_value(ostream& out, t_struct* tstruct);
+  void generate_standard_scheme_write_value(ostream& out, t_struct* tstruct);
+  void generate_tuple_scheme_read_value(ostream& out, t_struct* tstruct);
+  void generate_tuple_scheme_write_value(ostream& out, t_struct* tstruct);
+  void generate_get_field_desc(ostream& out, t_struct* tstruct);
+  void generate_get_struct_desc(ostream& out, t_struct* tstruct);
+  void generate_get_field_name(ostream& out, t_struct* tstruct);
 
-  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
-  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
+  void generate_union_comparisons(ostream& out, t_struct* tstruct);
+  void generate_union_hashcode(ostream& out, t_struct* tstruct);
 
-  void generate_scheme_map(ofstream& out, t_struct* tstruct);
-  void generate_standard_writer(ofstream& out, t_struct* tstruct, bool is_result);
-  void generate_standard_reader(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_scheme_map(ostream& out, t_struct* tstruct);
+  void generate_standard_writer(ostream& out, t_struct* tstruct, bool is_result);
+  void generate_standard_reader(ostream& out, t_struct* tstruct);
+  void generate_java_struct_standard_scheme(ostream& out, t_struct* tstruct, bool is_result);
 
-  void generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_scheme(ostream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_reader(ostream& out, t_struct* tstruct);
+  void generate_java_struct_tuple_writer(ostream& out, t_struct* tstruct);
 
-  void generate_java_scheme_lookup(ofstream& out);
+  void generate_java_scheme_lookup(ostream& out);
 
-  void generate_javax_generated_annotation(ofstream& out);
+  void generate_javax_generated_annotation(ostream& out);
   /**
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   bool has_metadata = true);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out,
+  void generate_deserialize_container(std::ostream& out,
                                       t_type* ttype,
                                       std::string prefix = "",
                                       bool has_metadata = true);
 
-  void generate_deserialize_set_element(std::ofstream& out,
+  void generate_deserialize_set_element(std::ostream& out,
                                         t_set* tset,
                                         std::string prefix = "",
                                         std::string obj = "",
                                         bool has_metadata = true);
 
-  void generate_deserialize_map_element(std::ofstream& out,
+  void generate_deserialize_map_element(std::ostream& out,
                                         t_map* tmap,
                                         std::string prefix = "",
                                         std::string obj = "",
                                         bool has_metadata = true);
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "",
                                          std::string obj = "",
                                          bool has_metadata = true);
 
-  void generate_serialize_field(std::ofstream& out,
+  void generate_serialize_field(std::ostream& out,
                                 t_field* tfield,
                                 std::string prefix = "",
                                 bool has_metadata = true);
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out,
+  void generate_serialize_container(std::ostream& out,
                                     t_type* ttype,
                                     std::string prefix = "",
                                     bool has_metadata = true);
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map,
                                       bool has_metadata = true);
 
-  void generate_serialize_set_element(std::ofstream& out,
+  void generate_serialize_set_element(std::ostream& out,
                                       t_set* tmap,
                                       std::string iter,
                                       bool has_metadata = true);
 
-  void generate_serialize_list_element(std::ofstream& out,
+  void generate_serialize_list_element(std::ostream& out,
                                        t_list* tlist,
                                        std::string iter,
                                        bool has_metadata = true);
 
-  void generate_deep_copy_container(std::ofstream& out,
+  void generate_deep_copy_container(std::ostream& out,
                                     std::string source_name_p1,
                                     std::string source_name_p2,
                                     std::string result_name,
                                     t_type* type);
-  void generate_deep_copy_non_container(std::ofstream& out,
+  void generate_deep_copy_non_container(std::ostream& out,
                                         std::string source_name,
                                         std::string dest_name,
                                         t_type* type);
@@ -309,6 +313,7 @@
 
   std::string java_package();
   std::string java_suppressions();
+  std::string java_nullable_annotation();
   std::string type_name(t_type* ttype,
                         bool in_container = false,
                         bool in_init = false,
@@ -329,9 +334,9 @@
                                   t_type* ttype,
                                   bool include_types = false);
   std::string type_to_enum(t_type* ttype);
-  void generate_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_field_descs(ofstream& out, t_struct* tstruct);
-  void generate_field_name_constants(ofstream& out, t_struct* tstruct);
+  void generate_struct_desc(ostream& out, t_struct* tstruct);
+  void generate_field_descs(ostream& out, t_struct* tstruct);
+  void generate_field_name_constants(ostream& out, t_struct* tstruct);
 
   std::string make_valid_java_filename(std::string const& fromName);
   std::string make_valid_java_identifier(std::string const& fromName);
@@ -393,7 +398,7 @@
    */
 
   std::string package_name_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
   std::string package_dir_;
 
   bool bean_style_;
@@ -408,7 +413,8 @@
   bool use_option_type_;
   bool undated_generated_annotations_;
   bool suppress_generated_annotations_;
-  bool handle_runtime_exceptions_;
+  bool rethrow_unhandled_exceptions_;
+  bool unsafe_binaries_;
 
 };
 
@@ -455,6 +461,10 @@
   return "@SuppressWarnings({\"cast\", \"rawtypes\", \"serial\", \"unchecked\", \"unused\"})\n";
 }
 
+string t_java_generator::java_nullable_annotation() {
+  return "@org.apache.thrift.annotation.Nullable";
+}
+
 /**
  * Nothing in Java
  */
@@ -481,13 +491,18 @@
   bool is_deprecated = this->is_deprecated(tenum->annotations_);
   // Make output file
   string f_enum_name = package_dir_ + "/" + make_valid_java_filename(tenum->get_name()) + ".java";
-  ofstream f_enum;
+  ofstream_with_content_based_conditional_update f_enum;
   f_enum.open(f_enum_name.c_str());
 
   // Comment and package it
   f_enum << autogen_comment() << java_package() << endl;
 
   generate_java_doc(f_enum, tenum);
+
+  if (!suppress_generated_annotations_) {
+    generate_javax_generated_annotation(f_enum);
+  }
+
   if (is_deprecated) {
     indent(f_enum) << "@Deprecated" << endl;
   }
@@ -534,6 +549,7 @@
                  << endl;
   indent(f_enum) << " * @return null if the value is not found." << endl;
   indent(f_enum) << " */" << endl;
+  indent(f_enum) << java_nullable_annotation() << endl;
   indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl;
 
   indent_up();
@@ -573,7 +589,7 @@
 
   string f_consts_name = package_dir_ + '/' + make_valid_java_filename(program_name_)
                          + "Constants.java";
-  ofstream f_consts;
+  ofstream_with_content_based_conditional_update f_consts;
   f_consts.open(f_consts_name.c_str());
 
   // Print header
@@ -596,12 +612,13 @@
   f_consts.close();
 }
 
+
 /**
  * Prints the value of a constant with the given type. Note that type checking
  * is NOT performed in this function as it is always run beforehand using the
  * validate_types method in main.cc
  */
-void t_java_generator::print_const_value(std::ofstream& out,
+void t_java_generator::print_const_value(std::ostream& out,
                                          string name,
                                          t_type* type,
                                          t_const_value* value,
@@ -619,10 +636,12 @@
   } else if (type->is_enum()) {
     out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl;
   } else if (type->is_struct() || type->is_xception()) {
-    const vector<t_field*>& fields = ((t_struct*)type)->get_members();
+    const vector<t_field*>& unsorted_fields = ((t_struct*)type)->get_members();
+    vector<t_field*> fields = unsorted_fields;
+    std::sort(fields.begin(), fields.end(), t_field::key_compare());
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     out << name << " = new " << type_name(type, false, true) << "();" << endl;
     if (!in_static) {
       indent(out) << "static {" << endl;
@@ -660,8 +679,8 @@
     }
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, ktype, v_iter->first);
       string val = render_const_value(out, vtype, v_iter->second);
@@ -704,7 +723,7 @@
   }
 }
 
-string t_java_generator::render_const_value(ofstream& out, t_type* type, t_const_value* value) {
+string t_java_generator::render_const_value(ostream& out, t_type* type, t_const_value* value) {
   type = get_true_type(type);
   std::ostringstream render;
 
@@ -731,9 +750,9 @@
       break;
     case t_base_type::TYPE_DOUBLE:
       if (value->get_type() == t_const_value::CV_INTEGER) {
-        render << "(double)" << value->get_integer();
+        render << value->get_integer() << "d";
       } else {
-        render << value->get_double();
+        render << emit_double_as_string(value->get_double());
       }
       break;
     default:
@@ -786,7 +805,7 @@
   // Make output file
   string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
                          + ".java";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << java_package() << java_suppressions();
@@ -804,7 +823,7 @@
   // Make output file
   string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name())
                          + ".java";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << java_package() << java_suppressions();
@@ -814,6 +833,10 @@
   bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
   bool is_deprecated = this->is_deprecated(tstruct->annotations_);
 
+  if (!suppress_generated_annotations_) {
+    generate_javax_generated_annotation(f_struct);
+  }
+
   if (is_deprecated) {
     indent(f_struct) << "@Deprecated" << endl;
   }
@@ -875,7 +898,7 @@
   f_struct.close();
 }
 
-void t_java_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_constructor(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -925,15 +948,19 @@
                   << "(byte[] value) {" << endl;
       indent(out) << "  " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();"
                   << endl;
-      indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name())
-                  << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl;
+      indent(out) << "  x.set" << get_cap_name((*m_iter)->get_name());
+      if(unsafe_binaries_) {
+        indent(out) << "(java.nio.ByteBuffer.wrap(value));" << endl;
+      }else{
+        indent(out) << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl;
+      }
       indent(out) << "  return x;" << endl;
       indent(out) << "}" << endl << endl;
     }
   }
 }
 
-void t_java_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_getters_and_setters(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -968,9 +995,17 @@
                   << get_cap_name(field->get_name()) << "() {" << endl;
       indent(out) << "  if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {"
                   << endl;
-      indent(out)
+
+      if(unsafe_binaries_){
+        indent(out)
+          << "    return (java.nio.ByteBuffer)getFieldValue();"
+          << endl;
+      }else{
+        indent(out)
           << "    return org.apache.thrift.TBaseHelper.copyBinary((java.nio.ByteBuffer)getFieldValue());"
           << endl;
+      }
+
       indent(out) << "  } else {" << endl;
       indent(out) << "    throw new java.lang.RuntimeException(\"Cannot get field '" << field->get_name()
                   << "' because union is currently set to \" + getFieldDesc(getSetField()).name);"
@@ -1004,8 +1039,14 @@
       }
       indent(out) << "public void set" << get_cap_name(field->get_name()) << "(byte[] value) {"
                   << endl;
-      indent(out) << "  set" << get_cap_name(field->get_name())
-                  << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl;
+      indent(out) << "  set" << get_cap_name(field->get_name());
+
+      if(unsafe_binaries_){
+        indent(out) << "(java.nio.ByteBuffer.wrap(value));" << endl;
+      }else{
+        indent(out) << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl;
+      }
+
       indent(out) << "}" << endl;
 
       out << endl;
@@ -1024,7 +1065,7 @@
   }
 }
 
-void t_java_generator::generate_union_is_set_methods(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_is_set_methods(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -1047,7 +1088,7 @@
   }
 }
 
-void t_java_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_abstract_methods(ostream& out, t_struct* tstruct) {
   generate_check_type(out, tstruct);
   out << endl;
   generate_standard_scheme_read_value(out, tstruct);
@@ -1068,7 +1109,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_check_type(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out)
       << "protected void checkType(_Fields setField, java.lang.Object value) throws java.lang.ClassCastException {"
@@ -1105,7 +1146,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_standard_scheme_read_value(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "protected java.lang.Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol "
                  "iprot, org.apache.thrift.protocol.TField field) throws "
@@ -1161,7 +1202,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_standard_scheme_write_value(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol "
                  "oprot) throws org.apache.thrift.TException {" << endl;
@@ -1198,7 +1239,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_tuple_scheme_read_value(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "protected java.lang.Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol "
                  "iprot, short fieldID) throws org.apache.thrift.TException {" << endl;
@@ -1244,7 +1285,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_tuple_scheme_write_value(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) "
                  "throws org.apache.thrift.TException {" << endl;
@@ -1281,7 +1322,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_get_field_desc(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {"
               << endl;
@@ -1309,7 +1350,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_get_struct_desc(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "@Override" << endl;
   indent(out) << "protected org.apache.thrift.protocol.TStruct getStructDesc() {" << endl;
@@ -1317,7 +1358,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_comparisons(ostream& out, t_struct* tstruct) {
   // equality
   indent(out) << "public boolean equals(java.lang.Object other) {" << endl;
   indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
@@ -1348,7 +1389,7 @@
   out << endl;
 }
 
-void t_java_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_union_hashcode(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "@Override" << endl;
   indent(out) << "public int hashCode() {" << endl;
@@ -1378,7 +1419,7 @@
  * @param in_class     If inside a class, needs to be static class
  * @param is_result    If this is a result it needs a different writer
  */
-void t_java_generator::generate_java_struct_definition(ofstream& out,
+void t_java_generator::generate_java_struct_definition(ostream& out,
                                                        t_struct* tstruct,
                                                        bool is_exception,
                                                        bool in_class,
@@ -1535,9 +1576,15 @@
       if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
         t_type* type = get_true_type((*m_iter)->get_type());
         if (type->is_binary()) {
-          indent(out) << "this." << (*m_iter)->get_name()
-                      << " = org.apache.thrift.TBaseHelper.copyBinary(" << (*m_iter)->get_name()
-                      << ");" << endl;
+          if(unsafe_binaries_){
+            indent(out) << "this." << (*m_iter)->get_name()
+                        << " = " << (*m_iter)->get_name()
+                        << ";" << endl;
+          }else{
+            indent(out) << "this." << (*m_iter)->get_name()
+                        << " = org.apache.thrift.TBaseHelper.copyBinary(" << (*m_iter)->get_name()
+                        << ");" << endl;
+          }
         } else {
           indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";"
                       << endl;
@@ -1637,7 +1684,7 @@
 /**
  * generates parcelable interface implementation
  */
-void t_java_generator::generate_java_struct_parcelable(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_parcelable(ostream& out, t_struct* tstruct) {
   string tname = tstruct->get_name();
 
   const vector<t_field*>& members = tstruct->get_members();
@@ -1853,7 +1900,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_equality(ostream& out, t_struct* tstruct) {
   out << indent() << "@Override" << endl << indent() << "public boolean equals(java.lang.Object that) {"
       << endl;
   indent_up();
@@ -1984,7 +2031,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_java_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_compare_to(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
   indent_up();
@@ -2027,7 +2074,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_reader(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws "
                  "org.apache.thrift.TException {" << endl;
@@ -2039,7 +2086,7 @@
 
 // generates java method to perform various checks
 // (e.g. check that all required fields are set)
-void t_java_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl;
   indent_up();
 
@@ -2089,7 +2136,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_writer(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
                  "org.apache.thrift.TException {" << endl;
@@ -2108,7 +2155,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_result_writer(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws "
                  "org.apache.thrift.TException {" << endl;
@@ -2119,8 +2166,9 @@
   indent(out) << "  }" << endl << endl;
 }
 
-void t_java_generator::generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_field_by_id(ostream& out, t_struct* tstruct) {
   (void)tstruct;
+  indent(out) << java_nullable_annotation() << endl;
   indent(out) << "public _Fields fieldForId(int fieldId) {" << endl;
   indent(out) << "  return _Fields.findByThriftId(fieldId);" << endl;
   indent(out) << "}" << endl << endl;
@@ -2163,7 +2211,7 @@
   indent_down();
 }
 
-void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out,
+void t_java_generator::generate_generic_field_getters_setters(std::ostream& out,
                                                               t_struct* tstruct) {
   std::ostringstream getter_stream;
   std::ostringstream setter_stream;
@@ -2185,13 +2233,15 @@
 
   // create the setter
 
-  indent(out) << "public void setFieldValue(_Fields field, java.lang.Object value) {" << endl;
+  indent(out) << "public void setFieldValue(_Fields field, " << java_nullable_annotation()
+              << " java.lang.Object value) {" << endl;
   indent(out) << "  switch (field) {" << endl;
   out << setter_stream.str();
   indent(out) << "  }" << endl;
   indent(out) << "}" << endl << endl;
 
   // create the getter
+  indent(out) << java_nullable_annotation() << endl;
   indent(out) << "public java.lang.Object getFieldValue(_Fields field) {" << endl;
   indent_up();
   indent(out) << "switch (field) {" << endl;
@@ -2203,7 +2253,7 @@
 }
 
 // Creates a generic isSet method that takes the field number as argument
-void t_java_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -2238,7 +2288,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* tstruct) {
   isset_type issetType = needs_isset(tstruct);
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -2319,6 +2369,7 @@
         if (is_deprecated) {
           indent(out) << "@Deprecated" << endl;
         }
+        indent(out) << java_nullable_annotation() << endl;
         indent(out) << "public java.util.Iterator<" << type_name(element_type, true, false)
                     << "> get" << cap_name;
         out << get_cap_name("iterator() {") << endl;
@@ -2394,8 +2445,13 @@
 
       indent(out) << "public java.nio.ByteBuffer buffer" << get_cap_name("for") << cap_name << "() {"
                   << endl;
-      indent(out) << "  return org.apache.thrift.TBaseHelper.copyBinary(" << field_name << ");"
-                  << endl;
+      if(unsafe_binaries_){
+        indent(out) << "  return " << field_name << ";"
+                    << endl;
+      }else {
+        indent(out) << "  return org.apache.thrift.TBaseHelper.copyBinary(" << field_name << ");"
+                    << endl;
+      }
       indent(out) << "}" << endl << endl;
     } else {
       if (optional) {
@@ -2426,6 +2482,9 @@
         if (is_deprecated) {
           indent(out) << "@Deprecated" << endl;
         }
+        if (type_can_be_null(type)) {
+          indent(out) << java_nullable_annotation() << endl;
+        }
         indent(out) << "public " << type_name(type);
         if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
           out << " is";
@@ -2453,8 +2512,14 @@
         out << type_name(tstruct);
       }
       out << " set" << cap_name << "(byte[] " << field_name << ") {" << endl;
-      indent(out) << "  this." << field_name << " = " << field_name << " == null ? (java.nio.ByteBuffer)null"
-                  << " : java.nio.ByteBuffer.wrap(" << field_name << ".clone());" << endl;
+      indent(out) << "  this." << field_name << " = " << field_name << " == null ? (java.nio.ByteBuffer)null";
+
+      if(unsafe_binaries_){
+        indent(out) << " : java.nio.ByteBuffer.wrap(" << field_name << ");" << endl;
+      }else{
+        indent(out) << " : java.nio.ByteBuffer.wrap(" << field_name << ".clone());" << endl;
+      }
+                 
       if (!bean_style_) {
         indent(out) << "  return this;" << endl;
       }
@@ -2469,10 +2534,11 @@
     } else {
       out << type_name(tstruct);
     }
-    out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl;
+    out << " set" << cap_name << "(" << (type_can_be_null(type) ? (java_nullable_annotation() + " ") : "")
+        << type_name(type) << " " << field_name << ") {" << endl;
     indent_up();
     indent(out) << "this." << field_name << " = ";
-    if (type->is_binary()) {
+    if (type->is_binary() && !unsafe_binaries_) {
       out << "org.apache.thrift.TBaseHelper.copyBinary(" << field_name << ")";
     } else {
       out << field_name;
@@ -2548,7 +2614,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_struct_tostring(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_tostring(ostream& out, t_struct* tstruct) {
   out << indent() << "@Override" << endl << indent() << "public java.lang.String toString() {" << endl;
   indent_up();
 
@@ -2619,7 +2685,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_java_generator::generate_java_meta_data_map(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_meta_data_map(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -2720,7 +2786,7 @@
   }
 }
 
-void t_java_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+void t_java_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) {
   out << endl;
   indent_up();
   indent_up();
@@ -3579,8 +3645,8 @@
   indent(f_service_) << "}" << endl << endl;
 
   indent(f_service_) << "@Override" << endl;
-  indent(f_service_) << "protected boolean handleRuntimeExceptions() {" << endl;
-  indent(f_service_) << "  return " << ((handle_runtime_exceptions_) ? "true" : "false") << ";" << endl;
+  indent(f_service_) << "protected boolean rethrowUnhandledExceptions() {" << endl;
+  indent(f_service_) << "  return " << ((rethrow_unhandled_exceptions_) ? "true" : "false") << ";" << endl;
   indent(f_service_) << "}" << endl << endl;
 
   indent(f_service_) << "public " << resultname << " getResult(I iface, " << argsname
@@ -3669,7 +3735,7 @@
  * @param tfield The field
  * @param prefix The variable name or container for this field
  */
-void t_java_generator::generate_deserialize_field(ofstream& out,
+void t_java_generator::generate_deserialize_field(ostream& out,
                                                   t_field* tfield,
                                                   string prefix,
                                                   bool has_metadata) {
@@ -3736,7 +3802,7 @@
 /**
  * Generates an unserializer for a struct, invokes read()
  */
-void t_java_generator::generate_deserialize_struct(ofstream& out,
+void t_java_generator::generate_deserialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix) {
 
@@ -3755,7 +3821,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_java_generator::generate_deserialize_container(ofstream& out,
+void t_java_generator::generate_deserialize_container(ostream& out,
                                                       t_type* ttype,
                                                       string prefix,
                                                       bool has_metadata) {
@@ -3858,7 +3924,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_java_generator::generate_deserialize_map_element(ofstream& out,
+void t_java_generator::generate_deserialize_map_element(ostream& out,
                                                         t_map* tmap,
                                                         string prefix,
                                                         string obj,
@@ -3905,7 +3971,7 @@
 /**
  * Deserializes a set element
  */
-void t_java_generator::generate_deserialize_set_element(ofstream& out,
+void t_java_generator::generate_deserialize_set_element(ostream& out,
                                                         t_set* tset,
                                                         string prefix,
                                                         string obj,
@@ -3943,7 +4009,7 @@
 /**
  * Deserializes a list element
  */
-void t_java_generator::generate_deserialize_list_element(ofstream& out,
+void t_java_generator::generate_deserialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string prefix,
                                                          string obj,
@@ -3984,7 +4050,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_java_generator::generate_serialize_field(ofstream& out,
+void t_java_generator::generate_serialize_field(ostream& out,
                                                 t_field* tfield,
                                                 string prefix,
                                                 bool has_metadata) {
@@ -4057,7 +4123,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_java_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_java_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   out << indent() << prefix << ".write(oprot);" << endl;
 }
@@ -4068,7 +4134,7 @@
  * @param ttype  The type of container
  * @param prefix String prefix for fields
  */
-void t_java_generator::generate_serialize_container(ofstream& out,
+void t_java_generator::generate_serialize_container(ostream& out,
                                                     t_type* ttype,
                                                     string prefix,
                                                     bool has_metadata) {
@@ -4133,7 +4199,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_java_generator::generate_serialize_map_element(ofstream& out,
+void t_java_generator::generate_serialize_map_element(ostream& out,
                                                       t_map* tmap,
                                                       string iter,
                                                       string map,
@@ -4148,7 +4214,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_java_generator::generate_serialize_set_element(ofstream& out,
+void t_java_generator::generate_serialize_set_element(ostream& out,
                                                       t_set* tset,
                                                       string iter,
                                                       bool has_metadata) {
@@ -4159,7 +4225,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_java_generator::generate_serialize_list_element(ofstream& out,
+void t_java_generator::generate_serialize_list_element(ostream& out,
                                                        t_list* tlist,
                                                        string iter,
                                                        bool has_metadata) {
@@ -4279,11 +4345,15 @@
  */
 string t_java_generator::declare_field(t_field* tfield, bool init, bool comment) {
   // TODO(mcslee): do we ever need to initialize the field?
-  string result = type_name(tfield->get_type()) + " " + tfield->get_name();
+  string result = "";
+  t_type* ttype = get_true_type(tfield->get_type());
+  if (type_can_be_null(ttype)) {
+    result += java_nullable_annotation() + " ";
+  }
+  result += type_name(tfield->get_type()) + " " + tfield->get_name();
   if (init) {
-    t_type* ttype = get_true_type(tfield->get_type());
     if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
+      std::ofstream dummy;
       result += " = " + render_const_value(dummy, ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -4599,7 +4669,7 @@
   return constant_name;
 }
 
-void t_java_generator::generate_deep_copy_container(ofstream& out,
+void t_java_generator::generate_deep_copy_container(ostream& out,
                                                     std::string source_name_p1,
                                                     std::string source_name_p2,
                                                     std::string result_name,
@@ -4749,7 +4819,7 @@
   }
 }
 
-void t_java_generator::generate_deep_copy_non_container(ofstream& out,
+void t_java_generator::generate_deep_copy_non_container(ostream& out,
                                                         std::string source_name,
                                                         std::string dest_name,
                                                         t_type* type) {
@@ -4779,19 +4849,19 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_java_generator::generate_isset_set(ofstream& out, t_field* field, string prefix) {
+void t_java_generator::generate_isset_set(ostream& out, t_field* field, string prefix) {
   if (!type_can_be_null(field->get_type())) {
     indent(out) << prefix << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet")
                 << "(true);" << endl;
   }
 }
 
-void t_java_generator::generate_struct_desc(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_struct_desc(ostream& out, t_struct* tstruct) {
   indent(out) << "private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new "
                  "org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\");" << endl;
 }
 
-void t_java_generator::generate_field_descs(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_field_descs(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -4804,14 +4874,14 @@
   }
 }
 
-void t_java_generator::generate_scheme_map(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_scheme_map(ostream& out, t_struct* tstruct) {
   indent(out) << "private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new "
       << tstruct->get_name() << "StandardSchemeFactory();" << endl;
   indent(out) << "private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new "
       << tstruct->get_name() << "TupleSchemeFactory();" << endl;
 }
 
-void t_java_generator::generate_field_name_constants(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_field_name_constants(ostream& out, t_struct* tstruct) {
   indent(out) << "/** The set of fields this struct contains, along with convenience methods for "
                  "finding and manipulating them. */" << endl;
   indent(out) << "public enum _Fields implements org.apache.thrift.TFieldIdEnum {" << endl;
@@ -4847,6 +4917,7 @@
   indent(out) << " * Find the _Fields constant that matches fieldId, or null if its not found."
               << endl;
   indent(out) << " */" << endl;
+  indent(out) << java_nullable_annotation() << endl;
   indent(out) << "public static _Fields findByThriftId(int fieldId) {" << endl;
   indent_up();
   indent(out) << "switch(fieldId) {" << endl;
@@ -4882,6 +4953,7 @@
   indent(out) << " * Find the _Fields constant that matches name, or null if its not found."
               << endl;
   indent(out) << " */" << endl;
+  indent(out) << java_nullable_annotation() << endl;
   indent(out) << "public static _Fields findByName(java.lang.String name) {" << endl;
   indent(out) << "  return byName.get(name);" << endl;
   indent(out) << "}" << endl << endl;
@@ -4937,7 +5009,7 @@
   }
 }
 
-void t_java_generator::generate_java_struct_clear(std::ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_clear(std::ostream& out, t_struct* tstruct) {
   if (!java5_) {
     indent(out) << "@Override" << endl;
   }
@@ -5001,7 +5073,7 @@
 }
 
 // generates java method to serialize (in the Java sense) the object
-void t_java_generator::generate_java_struct_write_object(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_write_object(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out)
       << "private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {"
@@ -5017,7 +5089,7 @@
 }
 
 // generates java method to serialize (in the Java sense) the object
-void t_java_generator::generate_java_struct_read_object(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_read_object(ostream& out, t_struct* tstruct) {
   indent(out) << "private void readObject(java.io.ObjectInputStream in) throws "
                  "java.io.IOException, java.lang.ClassNotFoundException {" << endl;
   indent(out) << "  try {" << endl;
@@ -5046,7 +5118,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_java_generator::generate_standard_reader(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_standard_reader(ostream& out, t_struct* tstruct) {
   out << indent() << "public void read(org.apache.thrift.protocol.TProtocol iprot, "
       << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
   indent_up();
@@ -5136,7 +5208,7 @@
   out << indent() << "}" << endl;
 }
 
-void t_java_generator::generate_standard_writer(ofstream& out, t_struct* tstruct, bool is_result) {
+void t_java_generator::generate_standard_writer(ostream& out, t_struct* tstruct, bool is_result) {
   indent_up();
   out << indent() << "public void write(org.apache.thrift.protocol.TProtocol oprot, "
       << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
@@ -5189,7 +5261,7 @@
   indent_down();
 }
 
-void t_java_generator::generate_java_struct_standard_scheme(ofstream& out,
+void t_java_generator::generate_java_struct_standard_scheme(ostream& out,
                                                             t_struct* tstruct,
                                                             bool is_result) {
   indent(out) << "private static class " << tstruct->get_name()
@@ -5214,7 +5286,7 @@
   out << indent() << "}" << endl << endl;
 }
 
-void t_java_generator::generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_tuple_reader(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "public void read(org.apache.thrift.protocol.TProtocol prot, "
               << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
@@ -5255,7 +5327,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_tuple_writer(ostream& out, t_struct* tstruct) {
   indent(out) << "@Override" << endl;
   indent(out) << "public void write(org.apache.thrift.protocol.TProtocol prot, "
               << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
@@ -5309,7 +5381,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct) {
+void t_java_generator::generate_java_struct_tuple_scheme(ostream& out, t_struct* tstruct) {
   indent(out) << "private static class " << tstruct->get_name()
               << "TupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {" << endl;
   indent_up();
@@ -5330,7 +5402,7 @@
   out << indent() << "}" << endl << endl;
 }
 
-void t_java_generator::generate_java_scheme_lookup(ofstream& out) {
+void t_java_generator::generate_java_scheme_lookup(ostream& out) {
   indent(out) << "private static <S extends org.apache.thrift.scheme.IScheme> S scheme("
       << "org.apache.thrift.protocol.TProtocol proto) {" << endl;
   indent_up();
@@ -5342,7 +5414,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_java_generator::generate_javax_generated_annotation(ofstream& out) {
+void t_java_generator::generate_javax_generated_annotation(ostream& out) {
   time_t seconds = time(NULL);
   struct tm* now = localtime(&seconds);
   indent(out) << "@javax.annotation.Generated(value = \"" << autogen_summary() << "\"";
@@ -5367,9 +5439,9 @@
     "    android_legacy:  Do not use java.io.IOException(throwable) (available for Android 2.3 and "
     "above).\n"
     "    option_type:     Wrap optional fields in an Option type.\n"
-    "    handle_runtime_exceptions:\n"
-    "                     Send TApplicationException to the client when RuntimeException occurs on "
-    "the server. (Default behavior is to close the connection instead.)\n"
+    "    rethrow_unhandled_exceptions:\n"
+    "                     Enable rethrow of unhandled exceptions and let them propagate futher."
+    " (Default behavior is to catch and log it.)\n"
     "    java5:           Generate Java 1.5 compliant code (includes android_legacy flag).\n"
     "    reuse-objects:   Data objects will not be allocated, but existing instances will be used "
     "(read and write).\n"
@@ -5378,4 +5450,5 @@
     "set/map.\n"
     "    generated_annotations=[undated|suppress]:\n"
     "                     undated: suppress the date at @Generated annotations\n"
-    "                     suppress: suppress @Generated annotations entirely\n")
+    "                     suppress: suppress @Generated annotations entirely\n"
+    "    unsafe_binaries: Do not copy ByteBuffers in constructors, getters, and setters.\n")
diff --git a/compiler/cpp/src/thrift/generate/t_javame_generator.cc b/compiler/cpp/src/thrift/generate/t_javame_generator.cc
index 24b7560..fa743ca 100644
--- a/compiler/cpp/src/thrift/generate/t_javame_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_javame_generator.cc
@@ -31,7 +31,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -81,13 +81,13 @@
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
+  void print_const_value(std::ostream& out,
                          std::string name,
                          t_type* type,
                          t_const_value* value,
                          bool in_static,
                          bool defval = false);
-  std::string render_const_value(std::ofstream& out,
+  std::string render_const_value(std::ostream& out,
                                  std::string name,
                                  t_type* type,
                                  t_const_value* value);
@@ -98,20 +98,20 @@
 
   void generate_java_struct(t_struct* tstruct, bool is_exception);
 
-  void generate_java_struct_definition(std::ofstream& out,
+  void generate_java_struct_definition(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false,
                                        bool in_class = false,
                                        bool is_result = false);
-  void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_java_validator(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
-  void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
-  void generate_field_value_meta_data(std::ofstream& out, t_type* type);
+  void generate_java_struct_equality(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_compare_to(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_java_validator(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_tostring(std::ostream& out, t_struct* tstruct);
+  void generate_java_struct_clear(std::ostream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ostream& out, t_type* type);
   std::string get_java_type_string(t_type* type);
   void generate_reflection_setters(std::ostringstream& out,
                                    t_type* type,
@@ -121,14 +121,14 @@
                                    t_type* type,
                                    std::string field_name,
                                    std::string cap_name);
-  void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
-  void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
+  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct);
+  void generate_java_bean_boilerplate(std::ostream& out, t_struct* tstruct);
 
   void generate_function_helpers(t_function* tfunction);
   std::string get_cap_name(std::string name);
   std::string generate_isset_check(t_field* field);
   std::string generate_isset_check(std::string field);
-  void generate_isset_set(ofstream& out, t_field* field);
+  void generate_isset_set(ostream& out, t_field* field);
   std::string isset_field_id(t_field* field);
 
   void generate_primitive_service_interface(t_service* tservice);
@@ -139,66 +139,66 @@
   void generate_process_function(t_service* tservice, t_function* tfunction);
 
   void generate_java_union(t_struct* tstruct);
-  void generate_union_constructor(ofstream& out, t_struct* tstruct);
-  void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
-  void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
-  void generate_check_type(ofstream& out, t_struct* tstruct);
-  void generate_read_value(ofstream& out, t_struct* tstruct);
-  void generate_write_value(ofstream& out, t_struct* tstruct);
-  void generate_get_field_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_get_field_name(ofstream& out, t_struct* tstruct);
+  void generate_union_constructor(ostream& out, t_struct* tstruct);
+  void generate_union_getters_and_setters(ostream& out, t_struct* tstruct);
+  void generate_union_abstract_methods(ostream& out, t_struct* tstruct);
+  void generate_check_type(ostream& out, t_struct* tstruct);
+  void generate_read_value(ostream& out, t_struct* tstruct);
+  void generate_write_value(ostream& out, t_struct* tstruct);
+  void generate_get_field_desc(ostream& out, t_struct* tstruct);
+  void generate_get_struct_desc(ostream& out, t_struct* tstruct);
+  void generate_get_field_name(ostream& out, t_struct* tstruct);
 
-  void generate_union_comparisons(ofstream& out, t_struct* tstruct);
-  void generate_union_hashcode(ofstream& out, t_struct* tstruct);
+  void generate_union_comparisons(ostream& out, t_struct* tstruct);
+  void generate_union_hashcode(ostream& out, t_struct* tstruct);
 
   /**
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string iter,
                                       std::string map);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_java_doc(std::ofstream& out, t_field* field);
+  void generate_java_doc(std::ostream& out, t_field* field);
 
-  void generate_java_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_java_doc(std::ostream& out, t_doc* tdoc);
 
-  void generate_java_doc(std::ofstream& out, t_function* tdoc);
+  void generate_java_doc(std::ostream& out, t_function* tdoc);
 
-  void generate_java_docstring_comment(std::ofstream& out, string contents);
+  void generate_java_docstring_comment(std::ostream& out, string contents);
 
-  void generate_deep_copy_container(std::ofstream& out,
+  void generate_deep_copy_container(std::ostream& out,
                                     std::string source_name_p1,
                                     std::string source_name_p2,
                                     std::string result_name,
                                     t_type* type);
-  void generate_deep_copy_non_container(std::ofstream& out,
+  void generate_deep_copy_non_container(std::ostream& out,
                                         std::string source_name,
                                         std::string dest_name,
                                         t_type* type);
@@ -222,8 +222,8 @@
   std::string argument_list(t_struct* tstruct, bool include_types = true);
   std::string type_to_enum(t_type* ttype);
   std::string get_enum_class_name(t_type* type);
-  void generate_struct_desc(ofstream& out, t_struct* tstruct);
-  void generate_field_descs(ofstream& out, t_struct* tstruct);
+  void generate_struct_desc(ostream& out, t_struct* tstruct);
+  void generate_field_descs(ostream& out, t_struct* tstruct);
   std::string box_type(t_type* type, string value);
 
   bool type_can_be_null(t_type* ttype) {
@@ -241,7 +241,7 @@
    */
 
   std::string package_name_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_service_;
   std::string package_dir_;
 };
 
@@ -329,7 +329,7 @@
 void t_javame_generator::generate_enum(t_enum* tenum) {
   // Make output file
   string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".java";
-  ofstream f_enum;
+  ofstream_with_content_based_conditional_update f_enum;
   f_enum.open(f_enum_name.c_str());
 
   // Comment and package it
@@ -408,7 +408,7 @@
   }
 
   string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.java";
-  ofstream f_consts;
+  ofstream_with_content_based_conditional_update f_consts;
   f_consts.open(f_consts_name.c_str());
 
   // Print header
@@ -434,7 +434,7 @@
  * is NOT performed in this function as it is always run beforehand using the
  * validate_types method in main.cc
  */
-void t_javame_generator::print_const_value(std::ofstream& out,
+void t_javame_generator::print_const_value(std::ostream& out,
                                            string name,
                                            t_type* type,
                                            t_const_value* value,
@@ -454,8 +454,8 @@
   } else if (type->is_struct() || type->is_xception()) {
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     out << name << " = new " << type_name(type, false, true) << "();" << endl;
     if (!in_static) {
       indent(out) << "static {" << endl;
@@ -489,8 +489,8 @@
     }
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       string key = render_const_value(out, name, ktype, v_iter->first);
       string val = render_const_value(out, name, vtype, v_iter->second);
@@ -535,7 +535,7 @@
   }
 }
 
-string t_javame_generator::render_const_value(ofstream& out,
+string t_javame_generator::render_const_value(ostream& out,
                                               string name,
                                               t_type* type,
                                               t_const_value* value) {
@@ -638,7 +638,7 @@
 void t_javame_generator::generate_java_struct(t_struct* tstruct, bool is_exception) {
   // Make output file
   string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
@@ -655,7 +655,7 @@
 void t_javame_generator::generate_java_union(t_struct* tstruct) {
   // Make output file
   string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java";
-  ofstream f_struct;
+  ofstream_with_content_based_conditional_update f_struct;
   f_struct.open(f_struct_name.c_str());
 
   f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports();
@@ -699,7 +699,7 @@
   f_struct.close();
 }
 
-void t_javame_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_union_constructor(ostream& out, t_struct* tstruct) {
   indent(out) << "public " << type_name(tstruct) << "() {" << endl;
   indent(out) << "  super();" << endl;
   indent(out) << "}" << endl << endl;
@@ -730,7 +730,7 @@
   }
 }
 
-void t_javame_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_union_getters_and_setters(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -772,7 +772,7 @@
   }
 }
 
-void t_javame_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_union_abstract_methods(ostream& out, t_struct* tstruct) {
   generate_check_type(out, tstruct);
   out << endl;
   generate_read_value(out, tstruct);
@@ -785,7 +785,7 @@
   out << endl;
 }
 
-void t_javame_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_check_type(ostream& out, t_struct* tstruct) {
   indent(out)
       << "protected void checkType(_Fields setField, Object value) throws ClassCastException {"
       << endl;
@@ -821,7 +821,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_javame_generator::generate_read_value(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_read_value(ostream& out, t_struct* tstruct) {
   indent(out) << "protected Object readValue(TProtocol iprot, TField field) throws TException {"
               << endl;
 
@@ -875,7 +875,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_javame_generator::generate_write_value(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_write_value(ostream& out, t_struct* tstruct) {
   indent(out) << "protected void writeValue(TProtocol oprot) throws TException {" << endl;
 
   indent_up();
@@ -910,7 +910,7 @@
   indent(out) << "}" << endl;
 }
 
-void t_javame_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_get_field_desc(ostream& out, t_struct* tstruct) {
   indent(out) << "protected TField getFieldDesc(_Fields setField) {" << endl;
   indent_up();
 
@@ -936,14 +936,14 @@
   indent(out) << "}" << endl;
 }
 
-void t_javame_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_get_struct_desc(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "protected TStruct getStructDesc() {" << endl;
   indent(out) << "  return STRUCT_DESC;" << endl;
   indent(out) << "}" << endl;
 }
 
-void t_javame_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_union_comparisons(ostream& out, t_struct* tstruct) {
   // equality
   indent(out) << "public boolean equals(Object other) {" << endl;
   indent(out) << "  if (other instanceof " << tstruct->get_name() << ") {" << endl;
@@ -973,7 +973,7 @@
   out << endl;
 }
 
-void t_javame_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_union_hashcode(ostream& out, t_struct* tstruct) {
   (void)tstruct;
   indent(out) << "/**" << endl;
   indent(out)
@@ -995,7 +995,7 @@
  * @param in_class     If inside a class, needs to be static class
  * @param is_result    If this is a result it needs a different writer
  */
-void t_javame_generator::generate_java_struct_definition(ofstream& out,
+void t_javame_generator::generate_java_struct_definition(ostream& out,
                                                          t_struct* tstruct,
                                                          bool is_exception,
                                                          bool in_class,
@@ -1177,7 +1177,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_struct_equality(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_equality(ostream& out, t_struct* tstruct) {
   out << indent() << "public boolean equals(Object that) {" << endl;
   indent_up();
   out << indent() << "if (that == null)" << endl << indent() << "  return false;" << endl
@@ -1246,7 +1246,7 @@
   indent(out) << "}" << endl << endl;
 }
 
-void t_javame_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_compare_to(ostream& out, t_struct* tstruct) {
   indent(out) << "public int compareTo(Object otherObject) {" << endl;
   //  indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
   indent_up();
@@ -1297,7 +1297,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_reader(ostream& out, t_struct* tstruct) {
   out << indent() << "public void read(TProtocol iprot) throws TException {" << endl;
   indent_up();
 
@@ -1365,7 +1365,7 @@
 
 // generates java method to perform various checks
 // (e.g. check that all required fields are set)
-void t_javame_generator::generate_java_validator(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "public void validate() throws TException {" << endl;
   indent_up();
 
@@ -1390,7 +1390,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
   indent_up();
 
@@ -1449,7 +1449,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_struct_result_writer(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_result_writer(ostream& out, t_struct* tstruct) {
   out << indent() << "public void write(TProtocol oprot) throws TException {" << endl;
   indent_up();
 
@@ -1527,7 +1527,7 @@
   indent_down();
 }
 
-void t_javame_generator::generate_generic_field_getters_setters(std::ofstream& out,
+void t_javame_generator::generate_generic_field_getters_setters(std::ostream& out,
                                                                 t_struct* tstruct) {
   (void)out;
   std::ostringstream getter_stream;
@@ -1555,7 +1555,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_bean_boilerplate(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_bean_boilerplate(ostream& out, t_struct* tstruct) {
   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) {
@@ -1708,7 +1708,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_javame_generator::generate_java_struct_tostring(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_tostring(ostream& out, t_struct* tstruct) {
   out << indent() << "public String toString() {" << endl;
   indent_up();
 
@@ -1819,7 +1819,7 @@
   }
 }
 
-void t_javame_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type) {
+void t_javame_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) {
   out << endl;
   indent_up();
   indent_up();
@@ -1894,7 +1894,7 @@
              << endl << endl;
 
   string f_interface_name = package_dir_ + "/" + service_name_ + "Iface.java";
-  std::ofstream f_iface;
+  ofstream_with_content_based_conditional_update f_iface;
   f_iface.open(f_interface_name.c_str());
 
   string extends_iface = "";
@@ -2391,7 +2391,7 @@
  * @param tfield The field
  * @param prefix The variable name or container for this field
  */
-void t_javame_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_javame_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   if (type->is_void()) {
@@ -2455,7 +2455,7 @@
 /**
  * Generates an unserializer for a struct, invokes read()
  */
-void t_javame_generator::generate_deserialize_struct(ofstream& out,
+void t_javame_generator::generate_deserialize_struct(ostream& out,
                                                      t_struct* tstruct,
                                                      string prefix) {
   out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
@@ -2465,7 +2465,7 @@
 /**
  * Deserializes a container by reading its size and then iterating
  */
-void t_javame_generator::generate_deserialize_container(ofstream& out,
+void t_javame_generator::generate_deserialize_container(ostream& out,
                                                         t_type* ttype,
                                                         string prefix) {
   scope_up(out);
@@ -2527,7 +2527,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_javame_generator::generate_deserialize_map_element(ofstream& out,
+void t_javame_generator::generate_deserialize_map_element(ostream& out,
                                                           t_map* tmap,
                                                           string prefix) {
   string key = tmp("_key");
@@ -2548,7 +2548,7 @@
 /**
  * Deserializes a set element
  */
-void t_javame_generator::generate_deserialize_set_element(ofstream& out,
+void t_javame_generator::generate_deserialize_set_element(ostream& out,
                                                           t_set* tset,
                                                           string prefix) {
   string elem = tmp("_elem");
@@ -2565,7 +2565,7 @@
 /**
  * Deserializes a list element
  */
-void t_javame_generator::generate_deserialize_list_element(ofstream& out,
+void t_javame_generator::generate_deserialize_list_element(ostream& out,
                                                            t_list* tlist,
                                                            string prefix) {
   string elem = tmp("_elem");
@@ -2584,7 +2584,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_javame_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_javame_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2654,7 +2654,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_javame_generator::generate_serialize_struct(ofstream& out,
+void t_javame_generator::generate_serialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix) {
   (void)tstruct;
@@ -2667,7 +2667,7 @@
  * @param ttype  The type of container
  * @param prefix String prefix for fields
  */
-void t_javame_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_javame_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -2733,7 +2733,7 @@
 /**
  * Serializes the members of a map.
  */
-void t_javame_generator::generate_serialize_map_element(ofstream& out,
+void t_javame_generator::generate_serialize_map_element(ostream& out,
                                                         t_map* tmap,
                                                         string iter,
                                                         string map) {
@@ -2747,7 +2747,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_javame_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_javame_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2755,7 +2755,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_javame_generator::generate_serialize_list_element(ofstream& out,
+void t_javame_generator::generate_serialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string iter) {
   t_field efield(tlist->get_elem_type(), iter);
@@ -2847,7 +2847,7 @@
   if (init) {
     t_type* ttype = get_true_type(tfield->get_type());
     if (ttype->is_base_type() && tfield->get_value() != NULL) {
-      ofstream dummy;
+      std::ofstream dummy;
       result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
     } else if (ttype->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
@@ -2997,11 +2997,11 @@
   return constant_name;
 }
 
-void t_javame_generator::generate_java_docstring_comment(ofstream& out, string contents) {
+void t_javame_generator::generate_java_docstring_comment(ostream& out, string contents) {
   generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
 }
 
-void t_javame_generator::generate_java_doc(ofstream& out, t_field* field) {
+void t_javame_generator::generate_java_doc(ostream& out, t_field* field) {
   if (field->get_type()->is_enum()) {
     string combined_message = field->get_doc() + "\n@see " + get_enum_class_name(field->get_type());
     generate_java_docstring_comment(out, combined_message);
@@ -3013,7 +3013,7 @@
 /**
  * Emits a JavaDoc comment if the provided object has a doc in Thrift
  */
-void t_javame_generator::generate_java_doc(ofstream& out, t_doc* tdoc) {
+void t_javame_generator::generate_java_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_java_docstring_comment(out, tdoc->get_doc());
   }
@@ -3022,7 +3022,7 @@
 /**
  * Emits a JavaDoc comment if the provided function object has a doc in Thrift
  */
-void t_javame_generator::generate_java_doc(ofstream& out, t_function* tfunction) {
+void t_javame_generator::generate_java_doc(ostream& out, t_function* tfunction) {
   if (tfunction->has_doc()) {
     stringstream ss;
     ss << tfunction->get_doc();
@@ -3039,7 +3039,7 @@
   }
 }
 
-void t_javame_generator::generate_deep_copy_container(ofstream& out,
+void t_javame_generator::generate_deep_copy_container(ostream& out,
                                                       std::string source_name_p1,
                                                       std::string source_name_p2,
                                                       std::string result_name,
@@ -3169,7 +3169,7 @@
   }
 }
 
-void t_javame_generator::generate_deep_copy_non_container(ofstream& out,
+void t_javame_generator::generate_deep_copy_non_container(ostream& out,
                                                           std::string source_name,
                                                           std::string dest_name,
                                                           t_type* type) {
@@ -3200,7 +3200,7 @@
   return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
 }
 
-void t_javame_generator::generate_isset_set(ofstream& out, t_field* field) {
+void t_javame_generator::generate_isset_set(ostream& out, t_field* field) {
   if (!type_can_be_null(field->get_type())) {
     indent(out) << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);"
                 << endl;
@@ -3216,12 +3216,12 @@
   return package + type->get_name();
 }
 
-void t_javame_generator::generate_struct_desc(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_struct_desc(ostream& out, t_struct* tstruct) {
   indent(out) << "private static final TStruct STRUCT_DESC = new TStruct(\"" << tstruct->get_name()
               << "\");" << endl;
 }
 
-void t_javame_generator::generate_field_descs(ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_field_descs(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
@@ -3245,7 +3245,7 @@
   return false;
 }
 
-void t_javame_generator::generate_java_struct_clear(std::ofstream& out, t_struct* tstruct) {
+void t_javame_generator::generate_java_struct_clear(std::ostream& out, t_struct* tstruct) {
   indent(out) << "public void clear() {" << endl;
 
   const vector<t_field*>& members = tstruct->get_members();
diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc
index f45ef57..61782b9 100644
--- a/compiler/cpp/src/thrift/generate/t_js_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc
@@ -20,7 +20,9 @@
 #include <map>
 #include <string>
 #include <fstream>
+#include <iomanip>
 #include <iostream>
+#include <limits>
 #include <vector>
 #include <list>
 #include <cassert>
@@ -32,7 +34,7 @@
 #include "thrift/version.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -58,10 +60,11 @@
     gen_node_ = false;
     gen_jquery_ = false;
     gen_ts_ = false;
+    gen_es6_ = false;
 
     bool with_ns_ = false;
 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+    for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if( iter->first.compare("node") == 0) {
         gen_node_ = true;
       } else if( iter->first.compare("jquery") == 0) {
@@ -70,13 +73,15 @@
         gen_ts_ = true;
       } else if( iter->first.compare("with_ns") == 0) {
         with_ns_ = true;
+      } else if( iter->first.compare("es6") == 0) {
+        gen_es6_ = true;
       } else {
         throw "unknown option js:" + iter->first;
       }
     }
 
-    if (gen_node_ && gen_ts_) {
-      throw "Invalid switch: [-gen js:node,ts] options not compatible";
+    if (gen_es6_ && gen_jquery_) {
+      throw "Invalid switch: [-gen js:es6,jquery] options not compatible";
     }
 
     if (gen_node_ && gen_jquery_) {
@@ -88,6 +93,15 @@
       throw "Invalid switch: [-gen js:with_ns] is only valid when using node.js";
     }
 
+    // Depending on the processing flags, we will update these to be ES6 compatible
+    js_const_type_ = "var ";
+    js_let_type_ = "var ";
+    js_var_type_ = "var ";
+    if (gen_es6_) {
+      js_const_type_ = "const ";
+      js_let_type_ = "let ";
+    }
+
     if (gen_node_) {
       out_dir_base_ = "gen-nodejs";
       no_ns_ = !with_ns_;
@@ -126,12 +140,12 @@
    * Structs!
    */
   void generate_js_struct(t_struct* tstruct, bool is_exception);
-  void generate_js_struct_definition(std::ofstream& out,
+  void generate_js_struct_definition(std::ostream& out,
                                      t_struct* tstruct,
                                      bool is_xception = false,
                                      bool is_exported = true);
-  void generate_js_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_js_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_js_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_js_struct_writer(std::ostream& out, t_struct* tstruct);
   void generate_js_function_helpers(t_function* tfunction);
 
   /**
@@ -148,43 +162,44 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   bool inclass = false);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
   /**
    * Helper rendering functions
    */
 
   std::string js_includes();
+  std::string ts_includes();
   std::string render_includes();
   std::string declare_field(t_field* tfield, bool init = false, bool obj = false);
   std::string function_signature(t_function* tfunction,
@@ -267,7 +282,7 @@
    * TypeScript Definition File helper functions
    */
 
-  string ts_function_signature(t_function* tfunction, bool include_callback);
+  string ts_function_signature(t_function* tfunction, bool include_callback, bool optional_callback);
   string ts_get_type(t_type* type);
 
   /**
@@ -284,11 +299,11 @@
   string ts_declare() { return (ts_module_.empty() ? "declare " : ""); }
 
   /**
-   * Returns "?" if the given field is optional.
+   * Returns "?" if the given field is optional or has a default value.
    * @param t_field The field to check
    * @return string
    */
-  string ts_get_req(t_field* field) { return (field->get_req() == t_field::T_OPTIONAL ? "?" : ""); }
+  string ts_get_req(t_field* field) {return (field->get_req() == t_field::T_OPTIONAL || field->get_value() != NULL ? "?" : ""); }
 
   /**
    * Returns the documentation, if the provided documentable object has one.
@@ -328,6 +343,11 @@
   bool gen_ts_;
 
   /**
+   * True if we should generate ES6 code, i.e. with Promises
+   */
+  bool gen_es6_;
+
+  /**
    * The name of the defined module(s), for TypeScript Definition Files.
    */
   string ts_module_;
@@ -338,12 +358,27 @@
   bool no_ns_;
 
   /**
+   * The variable decorator for "const" variables. Will default to "var" if in an incompatible language.
+   */
+  string js_const_type_;
+
+   /**
+   * The variable decorator for "let" variables. Will default to "var" if in an incompatible language.
+   */
+  string js_let_type_;
+
+   /**
+   * The default variable decorator. Supports all javascript languages, but is not scoped to functions or closures.
+   */
+  string js_var_type_;
+
+  /**
    * File streams
    */
-  std::ofstream f_types_;
-  std::ofstream f_service_;
-  std::ofstream f_types_ts_;
-  std::ofstream f_service_ts_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_service_;
+  ofstream_with_content_based_conditional_update f_types_ts_;
+  ofstream_with_content_based_conditional_update f_service_ts_;
 };
 
 /**
@@ -370,18 +405,18 @@
   // Print header
   f_types_ << autogen_comment();
 
-  if (gen_node_ && no_ns_) {
+  if ((gen_node_ || gen_es6_) && no_ns_) {
     f_types_ << "\"use strict\";" << endl << endl;
   }
 
   f_types_ << js_includes() << endl << render_includes() << endl;
 
   if (gen_ts_) {
-    f_types_ts_ << autogen_comment() << endl;
+    f_types_ts_ << autogen_comment() << ts_includes() << endl;
   }
 
   if (gen_node_) {
-    f_types_ << "var ttypes = module.exports = {};" << endl;
+    f_types_ << js_const_type_ << "ttypes = module.exports = {};" << endl;
   }
 
   string pns;
@@ -408,10 +443,26 @@
  */
 string t_js_generator::js_includes() {
   if (gen_node_) {
+    string result = js_const_type_ + "thrift = require('thrift');\n"
+        + js_const_type_ + "Thrift = thrift.Thrift;\n";
+    if (!gen_es6_) {
+      result += js_const_type_ + "Q = thrift.Q;\n";
+    }
+    return result;
+  }
+
+  return "";
+}
+
+/**
+ * Prints standard ts imports
+ */
+string t_js_generator::ts_includes() {
+  if (gen_node_) {
     return string(
-        "var thrift = require('thrift');\n"
-        "var Thrift = thrift.Thrift;\n"
-        "var Q = thrift.Q;\n");
+        "import thrift = require('thrift');\n"
+        "import Thrift = thrift.Thrift;\n"
+        "import Q = thrift.Q;\n");
   }
 
   return "";
@@ -426,7 +477,7 @@
   if (gen_node_) {
     const vector<t_program*>& includes = program_->get_includes();
     for (size_t i = 0; i < includes.size(); ++i) {
-      result += "var " + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name()
+      result += js_const_type_ + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name()
                 + "_types');\n";
     }
     if (includes.size() > 0) {
@@ -478,8 +529,8 @@
 
   indent_up();
 
-  vector<t_enum_value*> constants = tenum->get_constants();
-  vector<t_enum_value*>::iterator c_iter;
+  vector<t_enum_value*> const& constants = tenum->get_constants();
+  vector<t_enum_value*>::const_iterator c_iter;
   for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
     int value = (*c_iter)->get_value();
     if (gen_ts_) {
@@ -515,7 +566,7 @@
   f_types_ << render_const_value(type, value) << ";" << endl;
 
   if (gen_ts_) {
-    f_types_ts_ << ts_print_doc(tconst) << ts_indent() << ts_declare() << "var " << name << ": "
+    f_types_ts_ << ts_print_doc(tconst) << ts_indent() << ts_declare() << js_const_type_ << name << ": "
                 << ts_get_type(type) << ";" << endl;
   }
 }
@@ -549,7 +600,7 @@
       if (value->get_type() == t_const_value::CV_INTEGER) {
         out << value->get_integer();
       } else {
-        out << value->get_double();
+        out << emit_double_as_string(value->get_double());
       }
       break;
     default:
@@ -562,8 +613,8 @@
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -589,8 +640,8 @@
     out << "{" << endl;
     indent_up();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       if (v_iter != val.begin())
         out << "," << endl;
@@ -669,7 +720,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_js_generator::generate_js_struct_definition(ofstream& out,
+void t_js_generator::generate_js_struct_definition(ostream& out,
                                                    t_struct* tstruct,
                                                    bool is_exception,
                                                    bool is_exported) {
@@ -677,17 +728,16 @@
   vector<t_field*>::const_iterator m_iter;
 
   if (gen_node_) {
-    string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : "var ";
-    if (is_exported) {
-      out << prefix << tstruct->get_name() << " = "
-          << "module.exports." << tstruct->get_name() << " = function(args) {" << endl;
-    } else {
-      out << prefix << tstruct->get_name() << " = function(args) {"
-          << endl;
+    string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : js_const_type_;
+    out << prefix << tstruct->get_name() <<
+      (is_exported ? " = module.exports." + tstruct->get_name() : "");
+    if (gen_ts_) {
+      f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class "
+                  << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "")
+                  << " {" << endl;
     }
   } else {
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {"
-        << endl;
+    out << js_namespace(tstruct->get_program()) << tstruct->get_name();
     if (gen_ts_) {
       f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class "
                   << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "")
@@ -695,11 +745,28 @@
     }
   }
 
+  if (gen_es6_) {
+    if (gen_node_ && is_exception) {
+      out << " = class extends Thrift.TException {" << endl;
+    } else {
+      out << " = class {" << endl;
+    }
+    indent_up();
+    indent(out) << "constructor(args) {" << endl;
+  } else {
+    out << " = function(args) {" << endl;
+  }
+
   indent_up();
 
+  // Call super() method on inherited Error class
   if (gen_node_ && is_exception) {
-    out << indent() << "Thrift.TException.call(this, \"" << js_namespace(tstruct->get_program())
+    if (gen_es6_) {
+      indent(out) << "super(args);" << endl;
+    } else {
+      indent(out) << "Thrift.TException.call(this, \"" << js_namespace(tstruct->get_program())
         << tstruct->get_name() << "\");" << endl;
+    }
     out << indent() << "this.name = \"" << js_namespace(tstruct->get_program())
         << tstruct->get_name() << "\";" << endl;
   }
@@ -715,8 +782,14 @@
       out << indent() << dval << ";" << endl;
     }
     if (gen_ts_) {
-      f_types_ts_ << ts_indent() << (*m_iter)->get_name() << ": "
-                  << ts_get_type((*m_iter)->get_type()) << ";" << endl;
+      if (gen_node_) {
+        f_types_ts_ << ts_indent() << "public " << (*m_iter)->get_name() << ": "
+                    << ts_get_type((*m_iter)->get_type()) << ";" << endl;
+      } else {
+        f_types_ts_ << ts_indent() << (*m_iter)->get_name() << ": "
+                    << ts_get_type((*m_iter)->get_type()) << ";" << endl;
+      }
+      
     }
   }
 
@@ -742,15 +815,17 @@
       }
     }
 
-    out << indent() << "if (args) {" << endl;
+    indent(out) << "if (args) {" << endl;
+    indent_up();
     if (gen_ts_) {
       f_types_ts_ << endl << ts_indent() << "constructor(args?: { ";
     }
 
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       t_type* t = get_true_type((*m_iter)->get_type());
-      out << indent() << indent() << "if (args." << (*m_iter)->get_name() << " !== undefined && args." << (*m_iter)->get_name() << " !== null) {"
-          << endl << indent() << indent() << indent() << "this." << (*m_iter)->get_name();
+      indent(out) << "if (args." << (*m_iter)->get_name() << " !== undefined && args." << (*m_iter)->get_name() << " !== null) {" << endl;
+      indent_up();
+      indent(out) << "this." << (*m_iter)->get_name();
 
       if (t->is_struct()) {
         out << (" = new " + js_type_namespace(t->get_program()) + t->get_name() +
@@ -789,68 +864,90 @@
         out << " = args." << (*m_iter)->get_name() << ";" << endl;
       }
 
+      indent_down();
       if (!(*m_iter)->get_req()) {
-        out << indent() << indent() << "} else {" << endl << indent() << indent() << indent()
-            << "throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, "
+        indent(out) << "} else {" << endl;
+         indent(out)
+            << "  throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, "
                "'Required field " << (*m_iter)->get_name() << " is unset!');" << endl;
       }
-      out << indent() << indent() << "}" << endl;
+      indent(out) << "}" << endl;
       if (gen_ts_) {
         f_types_ts_ << (*m_iter)->get_name() << ts_get_req(*m_iter) << ": "
                     << ts_get_type((*m_iter)->get_type()) << "; ";
       }
     }
-
+    indent_down();
     out << indent() << "}" << endl;
     if (gen_ts_) {
       f_types_ts_ << "});" << endl;
     }
   }
 
+  // Done with constructor
   indent_down();
-  out << "};" << endl;
+  if (gen_es6_) {
+    indent(out) << "}" << endl << endl;
+  } else {
+    indent(out) << "};" << endl;
+  }
+
   if (gen_ts_) {
     f_types_ts_ << ts_indent() << "}" << endl;
   }
 
-  if (is_exception) {
-    out << "Thrift.inherits(" << js_namespace(tstruct->get_program()) << tstruct->get_name()
-        << ", Thrift.TException);" << endl;
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.name = '"
-        << tstruct->get_name() << "';" << endl;
-  } else {
-    // init prototype
-    out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype = {};"
-        << endl;
+  if (!gen_es6_) {
+    if (is_exception) {
+      out << "Thrift.inherits(" << js_namespace(tstruct->get_program()) << tstruct->get_name()
+          << ", Thrift.TException);" << endl;
+      out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.name = '"
+          << tstruct->get_name() << "';" << endl;
+    } else {
+      // init prototype manually if we aren't using es6
+      out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype = {};"
+          << endl;
+    }
+
   }
 
   generate_js_struct_reader(out, tstruct);
   generate_js_struct_writer(out, tstruct);
+
+  // Close out the class definition
+  if (gen_es6_) {
+    indent_down();
+    indent(out) << "};" << endl;
+  }
 }
 
 /**
  * Generates the read() method for a struct
  */
-void t_js_generator::generate_js_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_js_generator::generate_js_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
-  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
-      << ".prototype.read = function(input) {" << endl;
+  if (gen_es6_) {
+    indent(out) << "read (input) {" << endl;
+  } else {
+    indent(out) << js_namespace(tstruct->get_program()) << tstruct->get_name()
+        << ".prototype.read = function(input) {" << endl;
+  }
 
   indent_up();
 
   indent(out) << "input.readStructBegin();" << endl;
 
   // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
+  indent(out) << "while (true) {" << endl;
 
-  scope_up(out);
+  indent_up();
 
-  indent(out) << "var ret = input.readFieldBegin();" << endl;
-  indent(out) << "var fname = ret.fname;" << endl;
-  indent(out) << "var ftype = ret.ftype;" << endl;
-  indent(out) << "var fid = ret.fid;" << endl;
+  indent(out) << js_const_type_ << "ret = input.readFieldBegin();" << endl;
+  indent(out) << js_const_type_ << "ftype = ret.ftype;" << endl;
+  if (!fields.empty()) {
+    indent(out) << js_const_type_ << "fid = ret.fid;" << endl;
+  }
 
   // Check for field STOP marker and break
   indent(out) << "if (ftype == Thrift.Type.STOP) {" << endl;
@@ -860,9 +957,9 @@
   indent(out) << "}" << endl;
   if (!fields.empty()) {
     // Switch statement on the field we are reading
-    indent(out) << "switch (fid)" << endl;
+    indent(out) << "switch (fid) {" << endl;
 
-    scope_up(out);
+    indent_up();
 
     // Generate deserialization code for known cases
     for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -904,19 +1001,28 @@
   indent(out) << "return;" << endl;
 
   indent_down();
-  out << indent() << "};" << endl << endl;
+
+  if (gen_es6_) {
+    indent(out) << "}" << endl << endl;
+  } else {
+    indent(out) << "};" << endl << endl;
+  }
 }
 
 /**
  * Generates the write() method for a struct
  */
-void t_js_generator::generate_js_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_js_generator::generate_js_struct_writer(ostream& out, t_struct* tstruct) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
-  out << js_namespace(tstruct->get_program()) << tstruct->get_name()
-      << ".prototype.write = function(output) {" << endl;
+  if (gen_es6_) {
+    indent(out) << "write (output) {" << endl;
+  } else {
+    indent(out) << js_namespace(tstruct->get_program()) << tstruct->get_name()
+        << ".prototype.write = function(output) {" << endl;
+  }
 
   indent_up();
 
@@ -946,7 +1052,11 @@
   out << indent() << "return;" << endl;
 
   indent_down();
-  out << indent() << "};" << endl << endl;
+  if (gen_es6_) {
+    out << indent() << "}" << endl << endl;
+  } else {
+    out << indent() << "};" << endl << endl;
+  }
 }
 
 /**
@@ -965,7 +1075,7 @@
 
   f_service_ << autogen_comment();
 
-  if (gen_node_ && no_ns_) {
+  if ((gen_node_ || gen_es6_) && no_ns_) {
     f_service_ << "\"use strict\";" << endl << endl;
   }
 
@@ -977,6 +1087,39 @@
                     << ".d.ts\" />" << endl;
     }
     f_service_ts_ << autogen_comment() << endl;
+    if (gen_node_) {
+      f_service_ts_ << ts_includes() << endl;
+      f_service_ts_ << "import ttypes = require('./" + program_->get_name() + "_types');" << endl;
+      // Generate type aliases
+      // enum
+      vector<t_enum*> const& enums = program_->get_enums();
+      vector<t_enum*>::const_iterator e_iter;
+      for (e_iter = enums.begin(); e_iter != enums.end(); ++e_iter) {
+        f_service_ts_ << "import " << (*e_iter)->get_name() << " = ttypes."
+                  << js_namespace(program_) << (*e_iter)->get_name() << endl;
+      }
+      // const
+      vector<t_const*> const& consts = program_->get_consts();
+      vector<t_const*>::const_iterator c_iter;
+      for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+        f_service_ts_ << "import " << (*c_iter)->get_name() << " = ttypes."
+                  << js_namespace(program_) << (*c_iter)->get_name() << endl;
+      }
+      // exception
+      vector<t_struct*> const& exceptions = program_->get_xceptions();
+      vector<t_struct*>::const_iterator x_iter;
+      for (x_iter = exceptions.begin(); x_iter != exceptions.end(); ++x_iter) {
+        f_service_ts_ << "import " << (*x_iter)->get_name() << " = ttypes."
+                  << js_namespace(program_) << (*x_iter)->get_name() << endl;
+      }
+      // structs
+      vector<t_struct*> const& structs = program_->get_structs();
+      vector<t_struct*>::const_iterator s_iter;
+      for (s_iter = structs.begin(); s_iter != structs.end(); ++s_iter) {
+        f_service_ts_ << "import " << (*s_iter)->get_name() << " = ttypes."
+                  << js_namespace(program_) << (*s_iter)->get_name() << endl;
+      }
+    }
     if (!ts_module_.empty()) {
       f_service_ts_ << "declare module " << ts_module_ << " {";
     }
@@ -984,15 +1127,15 @@
 
   if (gen_node_) {
     if (tservice->get_extends() != NULL) {
-      f_service_ << "var " << tservice->get_extends()->get_name() << " = require('./"
-                 << tservice->get_extends()->get_name() << "');" << endl << "var "
+      f_service_ << js_const_type_ <<  tservice->get_extends()->get_name() << " = require('./"
+                 << tservice->get_extends()->get_name() << "');" << endl << js_const_type_
                  << tservice->get_extends()->get_name()
                  << "Client = " << tservice->get_extends()->get_name() << ".Client;" << endl
-                 << "var " << tservice->get_extends()->get_name()
+                 << js_const_type_ << tservice->get_extends()->get_name()
                  << "Processor = " << tservice->get_extends()->get_name() << ".Processor;" << endl;
     }
 
-    f_service_ << "var ttypes = require('./" + program_->get_name() + "_types');" << endl;
+    f_service_ << js_const_type_ << "ttypes = require('./" + program_->get_name() + "_types');" << endl;
   }
 
   generate_service_helpers(tservice);
@@ -1022,38 +1165,77 @@
   vector<t_function*>::iterator f_iter;
 
   if (gen_node_) {
-    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
-    f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor = function(handler) ";
+    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_;
+    f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor";
+    if (gen_ts_) {
+      f_service_ts_ << endl << "declare class Processor ";
+      if (tservice->get_extends() != NULL) {
+        f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Processor ";
+      }
+      f_service_ts_ << "{" << endl;
+      indent_up();
+      f_service_ts_ << ts_indent() << "private _handler: Object;" << endl << endl;
+      f_service_ts_ << ts_indent() << "constructor(handler: Object);" << endl;
+      f_service_ts_ << ts_indent() << "process(input: Thrift.TJSONProtocol, output: Thrift.TJSONProtocol): void;" << endl;
+      indent_down();
+    }
   } else {
     f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Processor = "
-             << "exports.Processor = function(handler) ";
+             << "exports.Processor";
   }
 
-  scope_up(f_service_);
+  bool is_subclass_service = tservice->get_extends() != NULL;
 
-  f_service_ << indent() << "this._handler = handler;" << endl;
+  // ES6 Constructor
+  if (gen_es6_) {
+    if (is_subclass_service) {
+      f_service_ << " = class extends " << tservice->get_extends()->get_name() << "Processor {" << endl;
+    } else {
+      f_service_ << " = class {" << endl;
+    }
+    indent_up();
+    indent(f_service_) << "constructor(handler) {" << endl;
+  } else {
+    f_service_ << " = function(handler) {" << endl;
+  }
 
-  scope_down(f_service_);
-  f_service_ << ";" << endl;
+  indent_up();
+  if (gen_es6_ && is_subclass_service) {
+    indent(f_service_) << "super(handler);" << endl;
+  }
+  indent(f_service_) << "this._handler = handler;" << endl;
+  indent_down();
 
-  if (tservice->get_extends() != NULL) {
+  // Done with constructor
+  if (gen_es6_) {
+    indent(f_service_) << "}" << endl;
+  } else {
+    indent(f_service_) << "};" << endl;
+  }
+
+  // ES5 service inheritance
+  if (!gen_es6_ && is_subclass_service) {
     indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
                        << service_name_ << "Processor, " << tservice->get_extends()->get_name()
                        << "Processor);" << endl;
   }
 
   // Generate the server implementation
-  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                     << "Processor.prototype.process = function(input, output) ";
+  if (gen_es6_) {
+    indent(f_service_) << "process (input, output) {" << endl;
+  } else {
+    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                      << "Processor.prototype.process = function(input, output) {" << endl;
+  }
 
-  scope_up(f_service_);
+  indent_up();
 
-  f_service_ << indent() << "var r = input.readMessageBegin();" << endl << indent()
+  indent(f_service_) << js_const_type_ << "r = input.readMessageBegin();" << endl << indent()
              << "if (this['process_' + r.fname]) {" << endl << indent()
              << "  return this['process_' + r.fname].call(this, r.rseqid, input, output);" << endl
              << indent() << "} else {" << endl << indent() << "  input.skip(Thrift.Type.STRUCT);"
              << endl << indent() << "  input.readMessageEnd();" << endl << indent()
-             << "  var x = new "
+             << "  " << js_const_type_ << "x = new "
                 "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN_METHOD, "
                 "'Unknown function ' + r.fname);" << endl << indent()
              << "  output.writeMessageBegin(r.fname, Thrift.MessageType.EXCEPTION, r.rseqid);"
@@ -1061,13 +1243,26 @@
              << "  output.writeMessageEnd();" << endl << indent() << "  output.flush();" << endl
              << indent() << "}" << endl;
 
-  scope_down(f_service_);
-  f_service_ << ";" << endl;
+  indent_down();
+  if (gen_es6_) {
+    indent(f_service_) << "}" << endl;
+  } else {
+    indent(f_service_) << "};" << endl;
+  }
 
   // Generate the process subfunctions
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     generate_process_function(tservice, *f_iter);
   }
+
+  // Close off the processor class definition
+  if (gen_es6_) {
+    indent_down();
+    indent(f_service_) << "};" << endl;
+  }
+  if (gen_node_ && gen_ts_) {
+    f_service_ts_ << "}" << endl;
+  }
 }
 
 /**
@@ -1076,17 +1271,26 @@
  * @param tfunction The function to write a dispatcher for
  */
 void t_js_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
-  indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                     << "Processor.prototype.process_" + tfunction->get_name()
-                        + " = function(seqid, input, output) ";
+  if (gen_es6_) {
+    indent(f_service_) << "process_" + tfunction->get_name() + " (seqid, input, output) {" << endl;
+  } else {
+    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                      << "Processor.prototype.process_" + tfunction->get_name()
+                          + " = function(seqid, input, output) {" << endl;
+  }
+  if (gen_ts_) {
+    indent_up();
+    f_service_ts_ << ts_indent() << "process_" << tfunction->get_name() << "(seqid: number, input: Thrift.TJSONProtocol, output: Thrift.TJSONProtocol): void;" << endl;
+    indent_down();
+  }
 
-  scope_up(f_service_);
+  indent_up();
 
   string argsname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_args";
   string resultname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name()
                       + "_result";
 
-  f_service_ << indent() << "var args = new " << argsname << "();" << endl << indent()
+  indent(f_service_) << js_const_type_ << "args = new " << argsname << "();" << endl << indent()
              << "args.read(input);" << endl << indent() << "input.readMessageEnd();" << endl;
 
   // Generate the function call
@@ -1109,33 +1313,57 @@
     }
 
     f_service_ << ");" << endl;
-    scope_down(f_service_);
-    f_service_ << ";" << endl;
+    indent_down();
+
+    if (gen_es6_) {
+      indent(f_service_) << "}" << endl;
+    } else {
+      indent(f_service_) << "};" << endl;
+    }
     return;
   }
 
-  f_service_ << indent() << "if (this._handler." << tfunction->get_name()
+  // Promise style invocation
+  indent(f_service_) << "if (this._handler." << tfunction->get_name()
              << ".length === " << fields.size() << ") {" << endl;
   indent_up();
-  indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name() << ".bind(this._handler)";
 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    f_service_ << ", args." << (*f_iter)->get_name();
+  if (gen_es6_) {
+    indent(f_service_) << "Promise.resolve(this._handler." << tfunction->get_name() << ".bind(this._handler)(" << endl;
+  } else {
+    string maybeComma = (fields.size() > 0 ? "," : "");
+    indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name() << ".bind(this._handler)"
+                       << maybeComma << endl;
   }
 
-  f_service_ << ")" << endl;
   indent_up();
-  indent(f_service_) << ".then(function(result) {" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string maybeComma = (f_iter != fields.end() - 1 ? "," : "");
+    indent(f_service_) << "args." << (*f_iter)->get_name() << maybeComma << endl;
+  }
+  indent_down();
+
+  if (gen_es6_) {
+    indent(f_service_) << ")).then(result => {" << endl;
+  } else {
+    indent(f_service_) << ").then(function(result) {" << endl;
+  }
+
   indent_up();
-  f_service_ << indent() << "var result_obj = new " << resultname << "({success: result});" << endl
+  f_service_ << indent() << js_const_type_ << "result_obj = new " << resultname << "({success: result});" << endl
              << indent() << "output.writeMessageBegin(\"" << tfunction->get_name()
              << "\", Thrift.MessageType.REPLY, seqid);" << endl << indent()
              << "result_obj.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl
              << indent() << "output.flush();" << endl;
   indent_down();
-  indent(f_service_) << "}, function (err) {" << endl;
+
+  if (gen_es6_) {
+    indent(f_service_) << "}).catch(err => {" << endl;
+  } else {
+    indent(f_service_) << "}).catch(function (err) {" << endl;
+  }
   indent_up();
-  indent(f_service_) << "var result;" << endl;
+  indent(f_service_) << js_let_type_ << "result;" << endl;
 
   bool has_exception = false;
   t_struct* exceptions = tfunction->get_xceptions();
@@ -1183,7 +1411,9 @@
   indent_down();
   indent(f_service_) << "});" << endl;
   indent_down();
-  indent_down();
+  // End promise style invocation
+
+  // Callback style invocation
   indent(f_service_) << "} else {" << endl;
   indent_up();
   indent(f_service_) << "this._handler." << tfunction->get_name() << "(";
@@ -1192,9 +1422,13 @@
     f_service_ << "args." << (*f_iter)->get_name() << ", ";
   }
 
-  f_service_ << "function (err, result) {" << endl;
+  if (gen_es6_) {
+    f_service_ << "(err, result) => {" << endl;
+  } else {
+    f_service_ << "function (err, result) {" << endl;
+  }
   indent_up();
-  indent(f_service_) << "var result_obj;" << endl;
+  indent(f_service_) << js_let_type_ << "result_obj;" << endl;
 
   indent(f_service_) << "if ((err === null || typeof err === 'undefined')";
   if (has_exception) {
@@ -1227,8 +1461,15 @@
   indent(f_service_) << "});" << endl;
   indent_down();
   indent(f_service_) << "}" << endl;
+  // End callback style invocation
+
   indent_down();
-  indent(f_service_) << "};" << endl;
+
+  if (gen_es6_) {
+    indent(f_service_) << "}" << endl;
+  } else {
+    indent(f_service_) << "};" << endl;
+  }
 }
 
 /**
@@ -1302,33 +1543,73 @@
  * @param tservice The service to generate a server for.
  */
 void t_js_generator::generate_service_client(t_service* tservice) {
+
+  bool is_subclass_service = tservice->get_extends() != NULL;
+
   if (gen_node_) {
-    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : "var ";
-    f_service_ << prefix << service_name_ << "Client = "
-               << "exports.Client = function(output, pClass) {" << endl;
+    string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_;
+    f_service_ << prefix << service_name_ << "Client = " << "exports.Client";
+    if (gen_ts_) {
+      f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class "
+                    << "Client ";
+      if (tservice->get_extends() != NULL) {
+        f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Client ";
+      }
+      f_service_ts_ << "{" << endl;
+    }
   } else {
     f_service_ << js_namespace(tservice->get_program()) << service_name_
-               << "Client = function(input, output) {" << endl;
+               << "Client";
     if (gen_ts_) {
       f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class "
                     << service_name_ << "Client ";
-      if (tservice->get_extends() != NULL) {
+      if (is_subclass_service) {
         f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Client ";
       }
       f_service_ts_ << "{" << endl;
     }
   }
 
+  // ES6 Constructor
+  if (gen_es6_) {
+    if (is_subclass_service) {
+      f_service_ << " = class extends " << js_namespace(tservice->get_extends()->get_program())
+                       << tservice->get_extends()->get_name() << "Client {" << endl;
+    } else {
+      f_service_ << " = class {" << endl;
+    }
+    indent_up();
+    if (gen_node_) {
+      indent(f_service_) << "constructor(output, pClass) {" << endl;
+    } else {
+      indent(f_service_) << "constructor(input, output) {" << endl;
+    }
+  } else {
+    if (gen_node_) {
+      f_service_ << " = function(output, pClass) {" << endl;
+    } else {
+      f_service_ << " = function(input, output) {" << endl;
+    }
+  }
+
   indent_up();
 
   if (gen_node_) {
-    f_service_ << indent() << "  this.output = output;" << endl << indent()
-               << "  this.pClass = pClass;" << endl << indent() << "  this._seqid = 0;" << endl
-               << indent() << "  this._reqs = {};" << endl;
+    indent(f_service_) << "this.output = output;" << endl;
+    indent(f_service_) << "this.pClass = pClass;" << endl;
+    indent(f_service_) << "this._seqid = 0;" << endl;
+    indent(f_service_) << "this._reqs = {};" << endl;
+    if (gen_ts_) {
+      f_service_ts_ << ts_indent() << "private input: Thrift.TJSONProtocol;" << endl << ts_indent()
+                    << "private output: Thrift.TJSONProtocol;" << endl << ts_indent() << "private seqid: number;"
+                    << endl << endl << ts_indent()
+                    << "constructor(input: Thrift.TJSONProtocol, output?: Thrift.TJSONProtocol);"
+                    << endl;
+    }
   } else {
-    f_service_ << indent() << "  this.input = input;" << endl << indent()
-               << "  this.output = (!output) ? input : output;" << endl << indent()
-               << "  this.seqid = 0;" << endl;
+    indent(f_service_) << "this.input = input;" << endl;
+    indent(f_service_) << "this.output = (!output) ? input : output;" << endl;
+    indent(f_service_) << "this.seqid = 0;" << endl;
     if (gen_ts_) {
       f_service_ts_ << ts_indent() << "input: Thrift.TJSONProtocol;" << endl << ts_indent()
                     << "output: Thrift.TJSONProtocol;" << endl << ts_indent() << "seqid: number;"
@@ -1340,27 +1621,36 @@
 
   indent_down();
 
-  f_service_ << indent() << "};" << endl;
-
-  if (tservice->get_extends() != NULL) {
-    indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
-                       << service_name_ << "Client, "
-                       << js_namespace(tservice->get_extends()->get_program())
-                       << tservice->get_extends()->get_name() << "Client);" << endl;
+  if (gen_es6_) {
+    indent(f_service_) << "}" << endl;
   } else {
-    // init prototype
-    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype = {};" << endl;
+    indent(f_service_) << "};" << endl;
+    if (is_subclass_service) {
+      indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program())
+                        << service_name_ << "Client, "
+                        << js_namespace(tservice->get_extends()->get_program())
+                        << tservice->get_extends()->get_name() << "Client);" << endl;
+    } else {
+      // init prototype
+      indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                        << "Client.prototype = {};" << endl;
+    }
   }
 
   // utils for multiplexed services
   if (gen_node_) {
-    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype.seqid = function() { return this._seqid; };" << endl
-                       << js_namespace(tservice->get_program()) << service_name_
-                       << "Client.prototype.new_seqid = function() { return this._seqid += 1; };"
-                       << endl;
+    if (gen_es6_) {
+      indent(f_service_) << "seqid () { return this._seqid; }" << endl;
+      indent(f_service_) << "new_seqid () { return this._seqid += 1; }" << endl;
+    } else {
+      indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                        << "Client.prototype.seqid = function() { return this._seqid; };" << endl
+                        << js_namespace(tservice->get_program()) << service_name_
+                        << "Client.prototype.new_seqid = function() { return this._seqid += 1; };"
+                        << endl;
+    }
   }
+
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::const_iterator f_iter;
@@ -1372,24 +1662,46 @@
     string arglist = argument_list(arg_struct);
 
     // Open function
-    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype."
-               << function_signature(*f_iter, "", true) << " {" << endl;
+    f_service_ << endl;
+    if (gen_es6_) {
+      indent(f_service_) << funname << " (" << arglist << ") {" << endl;
+    } else {
+      indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype."
+                << function_signature(*f_iter, "", !gen_es6_) << " {" << endl;
+    }
 
     indent_up();
 
     if (gen_ts_) {
-      f_service_ts_ << ts_print_doc(*f_iter) <<
-          // function definition without callback
-          ts_indent() << ts_function_signature(*f_iter, false) << endl << ts_print_doc(*f_iter) <<
-          // overload with callback
-          ts_indent() << ts_function_signature(*f_iter, true) << endl;
+      // function definition without callback
+      f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, false, false) << endl;
+      if (!gen_es6_) {
+        // overload with callback
+        f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true, false) << endl;
+      } else {
+        // overload with callback
+        f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true, true) << endl;
+      }
     }
 
-    if (gen_node_) { // Node.js output      ./gen-nodejs
+    if (gen_es6_ && gen_node_) {
+      indent(f_service_) << "this._seqid = this.new_seqid();" << endl;
+      indent(f_service_) << js_const_type_ << "self = this;" << endl << indent()
+                 << "return new Promise((resolve, reject) => {" << endl;
+      indent_up();
+      indent(f_service_) << "self._reqs[self.seqid()] = (error, result) => {" << endl;
+      indent_up();
+      indent(f_service_) << "return error ? reject(error) : resolve(result);" << endl;
+      indent_down();
+      indent(f_service_) << "};" << endl;
+      indent(f_service_) << "self.send_" << funname << "(" << arglist << ");" << endl;
+      indent_down();
+      indent(f_service_) << "});" << endl;
+    } else if (gen_node_) { // Node.js output      ./gen-nodejs
       f_service_ << indent() << "this._seqid = this.new_seqid();" << endl << indent()
                  << "if (callback === undefined) {" << endl;
       indent_up();
-      f_service_ << indent() << "var _defer = Q.defer();" << endl << indent()
+      f_service_ << indent() << js_const_type_ << "_defer = Q.defer();" << endl << indent()
                  << "this._reqs[this.seqid()] = function(error, result) {" << endl;
       indent_up();
       indent(f_service_) << "if (error) {" << endl;
@@ -1412,6 +1724,19 @@
                  << "this.send_" << funname << "(" << arglist << ");" << endl;
       indent_down();
       indent(f_service_) << "}" << endl;
+    } else if (gen_es6_) {
+      f_service_ << indent() << js_const_type_ << "self = this;" << endl << indent()
+                 << "return new Promise((resolve, reject) => {" << endl;
+      indent_up();
+      f_service_ << indent() << "self.send_" << funname << "(" << arglist
+                 << (arglist.empty() ? "" : ", ") << "(error, result) => {" << endl;
+      indent_up();
+      indent(f_service_) << "return error ? reject(error) : resolve(result);" << endl;
+      indent_down();
+      f_service_ << indent() << "});" << endl;
+      indent_down();
+      f_service_ << indent() << "});" << endl;
+
     } else if (gen_jquery_) { // jQuery output       ./gen-js
       f_service_ << indent() << "if (callback === undefined) {" << endl;
       indent_up();
@@ -1426,7 +1751,7 @@
       indent_down();
       f_service_ << indent() << "} else {" << endl;
       indent_up();
-      f_service_ << indent() << "var postData = this.send_" << funname << "(" << arglist
+      f_service_ << indent() << js_const_type_ << "postData = this.send_" << funname << "(" << arglist
                  << (arglist.empty() ? "" : ", ") << "true);" << endl;
       f_service_ << indent() << "return this.output.getTransport()" << endl;
       indent_up();
@@ -1451,17 +1776,30 @@
 
     indent_down();
 
-    f_service_ << "};" << endl << endl;
+    if (gen_es6_) {
+      indent(f_service_) << "}" << endl << endl;
+    } else {
+      indent(f_service_) << "};" << endl << endl;
+    }
 
     // Send function
-    f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.send_"
-               << function_signature(*f_iter, "", !gen_node_) << " {" << endl;
+    if (gen_es6_) {
+      if (gen_node_) {
+        indent(f_service_) << "send_" << funname << " (" << arglist << ") {" << endl;
+      } else {
+        // ES6 js still uses callbacks here. Should refactor this to promise style later..
+        indent(f_service_) << "send_" << funname << " (" << argument_list(arg_struct, true) << ") {" << endl;
+      }
+    } else {
+      indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.send_"
+                << function_signature(*f_iter, "", !gen_node_) << " {" << endl;
+    }
 
     indent_up();
 
     std::string outputVar;
     if (gen_node_) {
-      f_service_ << indent() << "var output = new this.pClass(this.output);" << endl;
+      f_service_ << indent() << js_const_type_ << "output = new this.pClass(this.output);" << endl;
       outputVar = "output";
     } else {
       outputVar = "this.output";
@@ -1472,8 +1810,30 @@
 
     std::string messageType = (*f_iter)->is_oneway() ? "Thrift.MessageType.ONEWAY"
                                                      : "Thrift.MessageType.CALL";
+    // Build args
+    if (fields.size() > 0){
+      f_service_ << indent() << js_const_type_ << "params = {" << endl;
+      indent_up();
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        indent(f_service_) << (*fld_iter)->get_name() << ": " << (*fld_iter)->get_name();
+        if (fld_iter != fields.end()-1) {
+          f_service_ << "," << endl;
+        } else {
+          f_service_ << endl;
+        }
+      }
+      indent_down();
+      indent(f_service_) << "};" << endl;
+      indent(f_service_) << js_const_type_ << "args = new " << argsname << "(params);" << endl;
+    } else {
+      indent(f_service_) << js_const_type_ << "args = new " << argsname << "();" << endl;
+    }
 
-    // Serialize the request header
+
+    // Serialize the request header within try/catch
+    indent(f_service_) << "try {" << endl;
+    indent_up();
+
     if (gen_node_) {
       f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name()
                  << "', " << messageType << ", this.seqid());" << endl;
@@ -1482,47 +1842,62 @@
                  << "', " << messageType << ", this.seqid);" << endl;
     }
 
-    if (fields.size() > 0){
-      f_service_ << indent() << "var params = {" << endl;
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
-        f_service_ << indent() << indent() << (*fld_iter)->get_name() << ": " << (*fld_iter)->get_name();
-        if (fld_iter != fields.end()-1) {
-          f_service_ << "," << endl;
-        } else {
-          f_service_ << endl;
-        }
-      }
-      f_service_ << indent() << "};" << endl;
-      f_service_ << indent() << "var args = new " << argsname << "(params);" << endl;
-    } else {
-      f_service_ << indent() << "var args = new " << argsname << "();" << endl;
-    }
 
     // Write to the stream
     f_service_ << indent() << "args.write(" << outputVar << ");" << endl << indent() << outputVar
                << ".writeMessageEnd();" << endl;
 
     if (gen_node_) {
-      f_service_ << indent() << "return this.output.flush();" << endl;
+      if((*f_iter)->is_oneway()) {
+        f_service_ << indent() << "this.output.flush();" << endl;
+        f_service_ << indent() << js_const_type_ << "callback = this._reqs[this.seqid()] || function() {};" << endl;
+        f_service_ << indent() << "delete this._reqs[this.seqid()];" << endl;
+        f_service_ << indent() << "callback(null);" << endl;
+      } else {
+        f_service_ << indent() << "return this.output.flush();" << endl;
+      }
     } else {
       if (gen_jquery_) {
         f_service_ << indent() << "return this.output.getTransport().flush(callback);" << endl;
+      } else if (gen_es6_) {
+        f_service_ << indent() << js_const_type_ << "self = this;" << endl;
+        if((*f_iter)->is_oneway()) {
+          f_service_ << indent() << "this.output.getTransport().flush(true, null);" << endl;
+          f_service_ << indent() << "callback();" << endl;
+        } else {
+          f_service_ << indent() << "this.output.getTransport().flush(true, () => {" << endl;
+          indent_up();
+          f_service_ << indent() << js_let_type_ << "error = null, result = null;" << endl;
+          f_service_ << indent() << "try {" << endl;
+          f_service_ << indent() << "  result = self.recv_" << funname << "();" << endl;
+          f_service_ << indent() << "} catch (e) {" << endl;
+          f_service_ << indent() << "  error = e;" << endl;
+          f_service_ << indent() << "}" << endl;
+          f_service_ << indent() << "callback(error, result);" << endl;
+          indent_down();
+          f_service_ << indent() << "});" << endl;
+        }
       } else {
         f_service_ << indent() << "if (callback) {" << endl;
+        indent_up();
         if((*f_iter)->is_oneway()) {
-          f_service_ << indent() << "  this.output.getTransport().flush(true, null);" << endl;
+          f_service_ << indent() << "this.output.getTransport().flush(true, null);" << endl;
+          f_service_ << indent() << "callback();" << endl;
         } else {
-          f_service_ << indent() << "  var self = this;" << endl;
-          f_service_ << indent() << "  this.output.getTransport().flush(true, function() {" << endl;
-          f_service_ << indent() << "    var result = null;" << endl;
-          f_service_ << indent() << "    try {" << endl;
-          f_service_ << indent() << "      result = self.recv_" << funname << "();" << endl;
-          f_service_ << indent() << "    } catch (e) {" << endl;
-          f_service_ << indent() << "      result = e;" << endl;
-          f_service_ << indent() << "    }" << endl;
-          f_service_ << indent() << "    callback(result);" << endl;
-          f_service_ << indent() << "  });" << endl;
+          f_service_ << indent() << js_const_type_ << "self = this;" << endl;
+          f_service_ << indent() << "this.output.getTransport().flush(true, function() {" << endl;
+          indent_up();
+          f_service_ << indent() << js_let_type_ << "result = null;" << endl;
+          f_service_ << indent() << "try {" << endl;
+          f_service_ << indent() << "  result = self.recv_" << funname << "();" << endl;
+          f_service_ << indent() << "} catch (e) {" << endl;
+          f_service_ << indent() << "  result = e;" << endl;
+          f_service_ << indent() << "}" << endl;
+          f_service_ << indent() << "callback(result);" << endl;
+          indent_down();
+          f_service_ << indent() << "});" << endl;
         }
+        indent_down();
         f_service_ << indent() << "} else {" << endl;
         f_service_ << indent() << "  return this.output.getTransport().flush();" << endl;
         f_service_ << indent() << "}" << endl;
@@ -1530,27 +1905,61 @@
     }
 
     indent_down();
+    f_service_ << indent() << "}" << endl;
 
-    f_service_ << "};" << endl;
+    // Reset the transport and delete registered callback if there was a serialization error
+    f_service_ << indent() << "catch (e) {" << endl;
+    indent_up();
+    if (gen_node_) {
+      f_service_ << indent() << "delete this._reqs[this.seqid()];" << endl;
+      f_service_ << indent() << "if (typeof " << outputVar << ".reset === 'function') {" << endl;
+      f_service_ << indent() << "  " << outputVar << ".reset();" << endl;
+      f_service_ << indent() << "}" << endl;
+    } else {
+      f_service_ << indent() << "if (typeof " << outputVar << ".getTransport().reset === 'function') {" << endl;
+      f_service_ << indent() << "  " << outputVar << ".getTransport().reset();" << endl;
+      f_service_ << indent() << "}" << endl;
+    }
+    f_service_ << indent() << "throw e;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
 
+    indent_down();
+
+    // Close send function
+    if (gen_es6_) {
+      indent(f_service_) << "}" << endl;
+    } else {
+      indent(f_service_) << "};" << endl;
+    }
+
+    // Receive function
     if (!(*f_iter)->is_oneway()) {
       std::string resultname = js_namespace(tservice->get_program()) + service_name_ + "_"
                                + (*f_iter)->get_name() + "_result";
 
+      f_service_ << endl;
+      // Open receive function
       if (gen_node_) {
-        // Open function
-        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
-                   << "Client.prototype.recv_" << (*f_iter)->get_name()
-                   << " = function(input,mtype,rseqid) {" << endl;
+        if (gen_es6_) {
+          indent(f_service_) << "recv_" << (*f_iter)->get_name() << " (input, mtype, rseqid) {" << endl;
+        } else {
+          indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                      << "Client.prototype.recv_" << (*f_iter)->get_name()
+                      << " = function(input,mtype,rseqid) {" << endl;
+        }
       } else {
-        t_struct noargs(program_);
+        if (gen_es6_) {
+          indent(f_service_) << "recv_" << (*f_iter)->get_name() << " () {" << endl;
+        } else {
+          t_struct noargs(program_);
 
-        t_function recv_function((*f_iter)->get_returntype(),
-                                 string("recv_") + (*f_iter)->get_name(),
-                                 &noargs);
-        // Open function
-        f_service_ << endl << js_namespace(tservice->get_program()) << service_name_
-                   << "Client.prototype." << function_signature(&recv_function) << " {" << endl;
+          t_function recv_function((*f_iter)->get_returntype(),
+                                  string("recv_") + (*f_iter)->get_name(),
+                                  &noargs);
+          indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
+                    << "Client.prototype." << function_signature(&recv_function) << " {" << endl;
+        }
       }
 
       indent_up();
@@ -1563,21 +1972,23 @@
       }
 
       if (gen_node_) {
-        f_service_ << indent() << "var callback = this._reqs[rseqid] || function() {};" << endl
+        f_service_ << indent() << js_const_type_ << "callback = this._reqs[rseqid] || function() {};" << endl
                    << indent() << "delete this._reqs[rseqid];" << endl;
       } else {
-        f_service_ << indent() << "var ret = this.input.readMessageBegin();" << endl << indent()
-                   << "var fname = ret.fname;" << endl << indent() << "var mtype = ret.mtype;"
-                   << endl << indent() << "var rseqid = ret.rseqid;" << endl;
+        f_service_ << indent() << js_const_type_ << "ret = this.input.readMessageBegin();" << endl
+                   << indent() << js_const_type_ << "mtype = ret.mtype;" << endl;
       }
 
-      f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {" << endl << indent()
-                 << "  var x = new Thrift.TApplicationException();" << endl << indent()
-                 << "  x.read(" << inputVar << ");" << endl << indent() << "  " << inputVar
-                 << ".readMessageEnd();" << endl << indent() << "  " << render_recv_throw("x")
-                 << endl << indent() << "}" << endl;
+      f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {" << endl;
 
-      f_service_ << indent() << "var result = new " << resultname << "();" << endl << indent()
+      indent_up();
+      f_service_ << indent() << js_const_type_ << "x = new Thrift.TApplicationException();" << endl
+                 << indent() << "x.read(" << inputVar << ");" << endl
+                 << indent() << inputVar << ".readMessageEnd();" << endl
+                 << indent() << render_recv_throw("x") << endl;
+      scope_down(f_service_);
+
+      f_service_ << indent() << js_const_type_ << "result = new " << resultname << "();" << endl << indent()
                  << "result.read(" << inputVar << ");" << endl;
 
       f_service_ << indent() << inputVar << ".readMessageEnd();" << endl << endl;
@@ -1606,15 +2017,24 @@
         }
       }
 
-      // Close function
+      // Close receive function
       indent_down();
-      f_service_ << "};" << endl;
+      if (gen_es6_) {
+        indent(f_service_) << "}" << endl;
+      } else {
+        indent(f_service_) << "};" << endl;
+      }
     }
   }
 
+  // Finish class definitions
   if (gen_ts_) {
     f_service_ts_ << ts_indent() << "}" << endl;
   }
+  if (gen_es6_) {
+    indent_down();
+    f_service_ << "};" << endl;
+  }
 }
 
 std::string t_js_generator::render_recv_throw(std::string var) {
@@ -1636,7 +2056,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_js_generator::generate_deserialize_field(ofstream& out,
+void t_js_generator::generate_deserialize_field(ostream& out,
                                                 t_field* tfield,
                                                 string prefix,
                                                 bool inclass) {
@@ -1708,54 +2128,42 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_js_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_js_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   out << indent() << prefix << " = new " << js_type_namespace(tstruct->get_program())
       << tstruct->get_name() << "();" << endl << indent() << prefix << ".read(input);" << endl;
 }
 
-void t_js_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_js_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   string size = tmp("_size");
-  string ktype = tmp("_ktype");
-  string vtype = tmp("_vtype");
-  string etype = tmp("_etype");
   string rtmp3 = tmp("_rtmp3");
 
   t_field fsize(g_type_i32, size);
-  t_field fktype(g_type_i8, ktype);
-  t_field fvtype(g_type_i8, vtype);
-  t_field fetype(g_type_i8, etype);
-
-  out << indent() << "var " << size << " = 0;" << endl;
-  out << indent() << "var " << rtmp3 << ";" << endl;
 
   // Declare variables, read header
   if (ttype->is_map()) {
-    out << indent() << prefix << " = {};" << endl << indent() << "var " << ktype << " = 0;" << endl
-        << indent() << "var " << vtype << " = 0;" << endl;
+    out << indent() << prefix << " = {};" << endl;
 
-    out << indent() << rtmp3 << " = input.readMapBegin();" << endl;
-    out << indent() << ktype << " = " << rtmp3 << ".ktype;" << endl;
-    out << indent() << vtype << " = " << rtmp3 << ".vtype;" << endl;
-    out << indent() << size << " = " << rtmp3 << ".size;" << endl;
+    out << indent() << js_const_type_ << rtmp3 << " = input.readMapBegin();" << endl;
+    out << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl;
 
   } else if (ttype->is_set()) {
 
-    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
-        << indent() << rtmp3 << " = input.readSetBegin();" << endl << indent() << etype << " = "
-        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
+    out << indent() << prefix << " = [];" << endl
+        << indent() << js_const_type_ << rtmp3 << " = input.readSetBegin();" << endl
+        << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl;
 
   } else if (ttype->is_list()) {
 
-    out << indent() << prefix << " = [];" << endl << indent() << "var " << etype << " = 0;" << endl
-        << indent() << rtmp3 << " = input.readListBegin();" << endl << indent() << etype << " = "
-        << rtmp3 << ".etype;" << endl << indent() << size << " = " << rtmp3 << ".size;" << endl;
+    out << indent() << prefix << " = [];" << endl
+        << indent() << js_const_type_ << rtmp3 << " = input.readListBegin();" << endl
+        << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl;
   }
 
   // For loop iterates over elements
   string i = tmp("_i");
-  indent(out) << "for (var " << i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl;
+  indent(out) << "for (" << js_let_type_ << i << " = 0; " << i << " < " << size << "; ++" << i << ") {" << endl;
 
-  scope_up(out);
+  indent_up();
 
   if (ttype->is_map()) {
     if (!gen_node_) {
@@ -1787,7 +2195,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_js_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_js_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("key");
   string val = tmp("val");
   t_field fkey(tmap->get_key_type(), key);
@@ -1802,24 +2210,24 @@
   indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
 }
 
-void t_js_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_js_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("elem");
   t_field felem(tset->get_elem_type(), elem);
 
-  indent(out) << "var " << elem << " = null;" << endl;
+  indent(out) << js_let_type_ << elem << " = null;" << endl;
 
   generate_deserialize_field(out, &felem);
 
   indent(out) << prefix << ".push(" << elem << ");" << endl;
 }
 
-void t_js_generator::generate_deserialize_list_element(ofstream& out,
+void t_js_generator::generate_deserialize_list_element(ostream& out,
                                                        t_list* tlist,
                                                        string prefix) {
   string elem = tmp("elem");
   t_field felem(tlist->get_elem_type(), elem);
 
-  indent(out) << "var " << elem << " = null;" << endl;
+  indent(out) << js_let_type_ << elem << " = null;" << endl;
 
   generate_deserialize_field(out, &felem);
 
@@ -1832,7 +2240,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_js_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_js_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -1903,7 +2311,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_js_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_js_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << prefix << ".write(output);" << endl;
 }
@@ -1911,7 +2319,7 @@
 /**
  * Writes out a container
  */
-void t_js_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_js_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   if (ttype->is_map()) {
     indent(out) << "output.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
                 << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
@@ -1929,21 +2337,21 @@
   if (ttype->is_map()) {
     string kiter = tmp("kiter");
     string viter = tmp("viter");
-    indent(out) << "for (var " << kiter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << kiter << "))" << endl;
-    scope_up(out);
-    indent(out) << "var " << viter << " = " << prefix << "[" << kiter << "];" << endl;
+    indent(out) << "for (" << js_let_type_ << kiter << " in " << prefix << ") {" << endl;
+    indent_up();
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << kiter << ")) {" << endl;
+    indent_up();
+    indent(out) << js_let_type_ << viter << " = " << prefix << "[" << kiter << "];" << endl;
     generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
     scope_down(out);
     scope_down(out);
 
   } else if (ttype->is_set()) {
     string iter = tmp("iter");
-    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
-    scope_up(out);
+    indent(out) << "for (" << js_let_type_ << iter << " in " << prefix << ") {" << endl;
+    indent_up();
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << ")) {" << endl;
+    indent_up();
     indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
     generate_serialize_set_element(out, (t_set*)ttype, iter);
     scope_down(out);
@@ -1951,10 +2359,10 @@
 
   } else if (ttype->is_list()) {
     string iter = tmp("iter");
-    indent(out) << "for (var " << iter << " in " << prefix << ")" << endl;
-    scope_up(out);
-    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << "))" << endl;
-    scope_up(out);
+    indent(out) << "for (" << js_let_type_ << iter << " in " << prefix << ") {" << endl;
+    indent_up();
+    indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << ")) {" << endl;
+    indent_up();
     indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl;
     generate_serialize_list_element(out, (t_list*)ttype, iter);
     scope_down(out);
@@ -1974,7 +2382,7 @@
  * Serializes the members of a map.
  *
  */
-void t_js_generator::generate_serialize_map_element(ofstream& out,
+void t_js_generator::generate_serialize_map_element(ostream& out,
                                                     t_map* tmap,
                                                     string kiter,
                                                     string viter) {
@@ -1988,7 +2396,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_js_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_js_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
@@ -1996,7 +2404,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_js_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_js_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
@@ -2010,7 +2418,7 @@
   string result = "this." + tfield->get_name();
 
   if (!obj) {
-    result = "var " + tfield->get_name();
+    result = js_let_type_ + tfield->get_name();
   }
 
   if (init) {
@@ -2214,7 +2622,7 @@
  * @param bool in-/exclude the callback argument
  * @return String of rendered function definition
  */
-std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback) {
+std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback, bool optional_callback) {
   string str;
   const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -2230,7 +2638,29 @@
   }
 
   if (include_callback) {
-    str += "callback: (data: " + ts_get_type(tfunction->get_returntype()) + ")=>void): ";
+    string callback_optional_string = optional_callback ? "?" : "";
+    if (gen_node_) {
+      t_struct* exceptions = tfunction->get_xceptions();
+      string exception_types;
+      if (exceptions) {
+        const vector<t_field*>& members = exceptions->get_members();
+        for (vector<t_field*>::const_iterator it = members.begin(); it != members.end(); ++it) {
+          t_type* t = get_true_type((*it)->get_type());
+          if (it == members.begin()) {
+            exception_types = t->get_name();
+          } else {
+            exception_types += " | " + t->get_name();
+          }
+        }
+      }
+      if (exception_types == "") {
+        str += "callback" + callback_optional_string + ": (error: void, response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): ";
+      } else {
+        str += "callback" + callback_optional_string + ": (error: " + exception_types + ", response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): ";
+      }
+    } else {
+      str += "callback" + callback_optional_string + ": (data: " + ts_get_type(tfunction->get_returntype()) + ")=>void): ";
+    }
 
     if (gen_jquery_) {
       str += "JQueryPromise<" + ts_get_type(tfunction->get_returntype()) +">;";
@@ -2238,7 +2668,12 @@
       str += "void;";
     }
   } else {
-    str += "): " + ts_get_type(tfunction->get_returntype()) + ";";
+    if (gen_es6_) {
+      str += "): Promise<" + ts_get_type(tfunction->get_returntype()) + ">;";
+    }
+    else {
+      str += "): " + ts_get_type(tfunction->get_returntype()) + ";";
+    }
   }
 
   return str;
@@ -2282,4 +2717,5 @@
                           "    jquery:          Generate jQuery compatible code.\n"
                           "    node:            Generate node.js compatible code.\n"
                           "    ts:              Generate TypeScript definition files.\n"
-                          "    with_ns:         Create global namespace objects when using node.js\n")
+                          "    with_ns:         Create global namespace objects when using node.js\n"
+                          "    es6:             Create ES6 code with Promises\n")
diff --git a/compiler/cpp/src/thrift/generate/t_json_generator.cc b/compiler/cpp/src/thrift/generate/t_json_generator.cc
index 153ec35..cd53612 100644
--- a/compiler/cpp/src/thrift/generate/t_json_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_json_generator.cc
@@ -89,7 +89,7 @@
 private:
   bool should_merge_includes_;
 
-  std::ofstream f_json_;
+  ofstream_with_content_based_conditional_update f_json_;
   std::stack<bool> comma_needed_;
 
   template <typename T>
@@ -510,8 +510,8 @@
 
   case t_const_value::CV_MAP: {
     start_object(NO_INDENT);
-    std::map<t_const_value*, t_const_value*> map = value->get_map();
-    std::map<t_const_value*, t_const_value*>::iterator mit;
+    std::map<t_const_value*, t_const_value*, t_const_value::value_compare> map = value->get_map();
+    std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::iterator mit;
     for (mit = map.begin(); mit != map.end(); ++mit) {
       write_comma_if_needed();
       f_json_ << indent();
diff --git a/compiler/cpp/src/thrift/generate/t_lua_generator.cc b/compiler/cpp/src/thrift/generate/t_lua_generator.cc
index 92e6749..adee896 100644
--- a/compiler/cpp/src/thrift/generate/t_lua_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_lua_generator.cc
@@ -21,7 +21,7 @@
 #include "thrift/platform.h"
 #include "thrift/generate/t_oop_generator.h"
 
-using std::ofstream;
+using std::ostream;
 using std::string;
 using std::vector;
 using std::map;
@@ -80,65 +80,65 @@
   /**
    * Struct-level generation functions
    */
-  void generate_lua_struct_definition(std::ofstream& out,
+  void generate_lua_struct_definition(std::ostream& out,
                                       t_struct* tstruct,
                                       bool is_xception = false);
-  void generate_lua_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_lua_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_lua_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_lua_struct_writer(std::ostream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
    */
-  void generate_service_client(std::ofstream& out, t_service* tservice);
-  void generate_service_interface(std::ofstream& out, t_service* tservice);
-  void generate_service_processor(std::ofstream& out, t_service* tservice);
-  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
-  void generate_service_helpers(ofstream& out, t_service* tservice);
-  void generate_function_helpers(ofstream& out, t_function* tfunction);
+  void generate_service_client(std::ostream& out, t_service* tservice);
+  void generate_service_interface(std::ostream& out, t_service* tservice);
+  void generate_service_processor(std::ostream& out, t_service* tservice);
+  void generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction);
+  void generate_service_helpers(ostream& out, t_service* tservice);
+  void generate_function_helpers(ostream& out, t_function* tfunction);
 
   /**
    * Deserialization (Read)
    */
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   bool local,
                                   std::string prefix = "");
 
-  void generate_deserialize_struct(std::ofstream& out,
+  void generate_deserialize_struct(std::ostream& out,
                                    t_struct* tstruct,
                                    bool local,
                                    std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out,
+  void generate_deserialize_container(std::ostream& out,
                                       t_type* ttype,
                                       bool local,
                                       std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
   /**
    * Serialization (Write)
    */
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
   /**
    * Helper rendering functions
@@ -159,9 +159,9 @@
   /**
    * File streams
    */
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_consts_;
+  ofstream_with_content_based_conditional_update f_service_;
 };
 
 /**
@@ -276,8 +276,8 @@
 
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end();) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -308,8 +308,8 @@
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end();) {
       indent(out) << "[" << render_const_value(ktype, v_iter->first)
                   << "] = " << render_const_value(vtype, v_iter->second);
@@ -366,7 +366,7 @@
 /**
  * Generate a thrift struct or exception (lua table)
  */
-void t_lua_generator::generate_lua_struct_definition(ofstream& out,
+void t_lua_generator::generate_lua_struct_definition(ostream& out,
                                                      t_struct* tstruct,
                                                      bool is_exception) {
   vector<t_field*>::const_iterator m_iter;
@@ -402,7 +402,7 @@
 /**
  * Generate a struct/exception reader
  */
-void t_lua_generator::generate_lua_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_lua_generator::generate_lua_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -459,7 +459,7 @@
 /**
  * Generate a struct/exception writer
  */
-void t_lua_generator::generate_lua_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_lua_generator::generate_lua_struct_writer(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -527,7 +527,7 @@
   f_service_.close();
 }
 
-void t_lua_generator::generate_service_interface(ofstream& out, t_service* tservice) {
+void t_lua_generator::generate_service_interface(ostream& out, t_service* tservice) {
   string classname = tservice->get_name() + "Iface";
   t_service* extends_s = tservice->get_extends();
 
@@ -541,7 +541,7 @@
   out << "  __type = '" << classname << "'" << endl << "}" << endl << endl;
 }
 
-void t_lua_generator::generate_service_client(ofstream& out, t_service* tservice) {
+void t_lua_generator::generate_service_client(ostream& out, t_service* tservice) {
   string classname = tservice->get_name() + "Client";
   t_service* extends_s = tservice->get_extends();
 
@@ -637,7 +637,7 @@
   }
 }
 
-void t_lua_generator::generate_service_processor(ofstream& out, t_service* tservice) {
+void t_lua_generator::generate_service_processor(ostream& out, t_service* tservice) {
   string classname = tservice->get_name() + "Processor";
   t_service* extends_s = tservice->get_extends();
 
@@ -680,7 +680,7 @@
   }
 }
 
-void t_lua_generator::generate_process_function(ofstream& out,
+void t_lua_generator::generate_process_function(ostream& out,
                                                 t_service* tservice,
                                                 t_function* tfunction) {
   string classname = tservice->get_name() + "Processor";
@@ -731,7 +731,7 @@
 }
 
 // Service helpers
-void t_lua_generator::generate_service_helpers(ofstream& out, t_service* tservice) {
+void t_lua_generator::generate_service_helpers(ostream& out, t_service* tservice) {
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
 
@@ -743,7 +743,7 @@
   }
 }
 
-void t_lua_generator::generate_function_helpers(ofstream& out, t_function* tfunction) {
+void t_lua_generator::generate_function_helpers(ostream& out, t_function* tfunction) {
   if (!tfunction->is_oneway()) {
     t_struct result(program_, tfunction->get_name() + "_result");
     t_field success(tfunction->get_returntype(), "success", 0);
@@ -764,7 +764,7 @@
 /**
  * Deserialize (Read)
  */
-void t_lua_generator::generate_deserialize_field(ofstream& out,
+void t_lua_generator::generate_deserialize_field(ostream& out,
                                                  t_field* tfield,
                                                  bool local,
                                                  string prefix) {
@@ -825,7 +825,7 @@
   }
 }
 
-void t_lua_generator::generate_deserialize_struct(ofstream& out,
+void t_lua_generator::generate_deserialize_struct(ostream& out,
                                                   t_struct* tstruct,
                                                   bool local,
                                                   string prefix) {
@@ -833,7 +833,7 @@
               << endl << indent() << prefix << ":read(iprot)" << endl;
 }
 
-void t_lua_generator::generate_deserialize_container(ofstream& out,
+void t_lua_generator::generate_deserialize_container(ostream& out,
                                                      t_type* ttype,
                                                      bool local,
                                                      string prefix) {
@@ -883,7 +883,7 @@
   }
 }
 
-void t_lua_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_lua_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   // A map is represented by a table indexable by any lua type
   string key = tmp("_key");
   string val = tmp("_val");
@@ -896,7 +896,7 @@
   indent(out) << prefix << "[" << key << "] = " << val << endl;
 }
 
-void t_lua_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_lua_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   // A set is represented by a table indexed by the value
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
@@ -906,7 +906,7 @@
   indent(out) << prefix << "[" << elem << "] = " << elem << endl;
 }
 
-void t_lua_generator::generate_deserialize_list_element(ofstream& out,
+void t_lua_generator::generate_deserialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string prefix) {
   // A list is represented by a table indexed by integer values
@@ -922,7 +922,7 @@
 /**
  * Serialize (Write)
  */
-void t_lua_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_lua_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
   string name = prefix + tfield->get_name();
 
@@ -979,12 +979,12 @@
   }
 }
 
-void t_lua_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_lua_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << prefix << ":write(oprot)" << endl;
 }
 
-void t_lua_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_lua_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   // Begin writing
   if (ttype->is_map()) {
     indent(out) << "oprot:writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
@@ -1034,7 +1034,7 @@
   }
 }
 
-void t_lua_generator::generate_serialize_map_element(ofstream& out,
+void t_lua_generator::generate_serialize_map_element(ostream& out,
                                                      t_map* tmap,
                                                      string kiter,
                                                      string viter) {
@@ -1045,12 +1045,12 @@
   generate_serialize_field(out, &vfield, "");
 }
 
-void t_lua_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_lua_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
 
-void t_lua_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_lua_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc
index 8d157a9..d2e7da0 100644
--- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc
@@ -35,219 +35,133 @@
 
 #include "thrift/platform.h"
 #include "thrift/generate/t_oop_generator.h"
+#include "thrift/generate/t_netcore_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
 using std::vector;
 
-//TODO: check for indentation 
+//TODO: check for indentation
 //TODO: Do we need seqId_ in generation?
 
-static const string endl = "\n"; // avoid ostream << std::endl flushes
-
-struct member_mapping_scope
+t_netcore_generator::t_netcore_generator(t_program* program, const map<string, string>& parsed_options, const string& option_string)
+    : t_oop_generator(program)
 {
-    void* scope_member;
-    map<string, string> mapping_table;
-};
+    (void)option_string;
 
-class t_netcore_generator : public t_oop_generator
+    nullable_ = false;
+    hashcode_ = false;
+    union_ = false;
+    serialize_ = false;
+    wcf_ = false;
+    wcf_namespace_.clear();
+
+    map<string, string>::const_iterator iter;
+
+    for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter)
+    {
+        if (iter->first.compare("nullable") == 0)
+        {
+            nullable_ = true;
+        }
+        else if (iter->first.compare("hashcode") == 0)
+        {
+            hashcode_ = true;
+        }
+        else if (iter->first.compare("union") == 0)
+        {
+            union_ = true;
+        }
+        else if (iter->first.compare("serial") == 0)
+        {
+            serialize_ = true;
+            wcf_namespace_ = iter->second; // since there can be only one namespace
+        }
+        else if (iter->first.compare("wcf") == 0)
+        {
+            wcf_ = true;
+            wcf_namespace_ = iter->second;
+        }
+        else
+        {
+            throw "unknown option netcore:" + iter->first;
+        }
+    }
+
+    out_dir_base_ = "gen-netcore";
+}
+
+static string correct_function_name_for_async(string const& function_name)
 {
-public:
-    t_netcore_generator(t_program* program, const map<string, string>& parsed_options, const string& option_string)
-        : t_oop_generator(program)
+    string const async_end = "Async";
+    size_t i = function_name.find(async_end);
+    if (i != string::npos)
     {
-        (void)option_string;
-
-        nullable_ = false;
-        hashcode_ = false;
-        union_ = false;
-        serialize_ = false;
-        wcf_ = false;
-        wcf_namespace_.clear();
-
-        map<string, string>::const_iterator iter;
-
-        for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter)
-        {
-            if (iter->first.compare("nullable") == 0)
-            {
-                nullable_ = true;
-            }
-            else if (iter->first.compare("hashcode") == 0)
-            {
-                hashcode_ = true;
-            }
-            else if (iter->first.compare("union") == 0)
-            {
-                union_ = true;
-            }
-            else if (iter->first.compare("serial") == 0)
-            {
-                serialize_ = true;
-                wcf_namespace_ = iter->second; // since there can be only one namespace
-            }
-            else if (iter->first.compare("wcf") == 0)
-            {
-                wcf_ = true;
-                wcf_namespace_ = iter->second;
-            }
-            else
-            {
-                throw "unknown option netcore:" + iter->first;
-            }
-        }
-
-        out_dir_base_ = "gen-netcore";
+        return function_name + async_end;
     }
 
-    // overrides
-    void init_generator();
-    void close_generator();
-    void generate_consts(vector<t_const*> consts);
-    void generate_typedef(t_typedef* ttypedef);
-    void generate_enum(t_enum* tenum);
-    void generate_struct(t_struct* tstruct);
-    void generate_xception(t_struct* txception);
-    void generate_service(t_service* tservice);
+    return function_name;
+}
 
-    void generate_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset);
-    void generate_netcore_property(ofstream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = "");
-    bool print_const_value(ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false);
-    string render_const_value(ofstream& out, string name, t_type* type, t_const_value* value);
-    void print_const_constructor(ofstream& out, vector<t_const*> consts);
-    void print_const_def_value(ofstream& out, string name, t_type* type, t_const_value* value);
-    void generate_netcore_struct(t_struct* tstruct, bool is_exception);
-    void generate_netcore_union(t_struct* tunion);
-    void generate_netcore_struct_definition(ofstream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false);
-    void generate_netcore_union_definition(ofstream& out, t_struct* tunion);
-    void generate_netcore_union_class(ofstream& out, t_struct* tunion, t_field* tfield);
-    void generate_netcore_wcffault(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_reader(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_result_writer(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_writer(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_tostring(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_equals(ofstream& out, t_struct* tstruct);
-    void generate_netcore_struct_hashcode(ofstream& out, t_struct* tstruct);
-    void generate_netcore_union_reader(ofstream& out, t_struct* tunion);
-    void generate_function_helpers(ofstream& out, t_function* tfunction);
-    void generate_service_interface(ofstream& out, t_service* tservice);
-    void generate_service_helpers(ofstream& out, t_service* tservice);
-    void generate_service_client(ofstream& out, t_service* tservice);
-    void generate_service_server(ofstream& out, t_service* tservice);
-    void generate_process_function_async(ofstream& out, t_service* tservice, t_function* function);
-    void generate_deserialize_field(ofstream& out, t_field* tfield, string prefix = "", bool is_propertyless = false);
-    void generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix = "");
-    void generate_deserialize_container(ofstream& out, t_type* ttype, string prefix = "");
-    void generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix = "");
-    void generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix = "");
-    void generate_deserialize_list_element(ofstream& out, t_list* list, string prefix = "");
-    void generate_serialize_field(ofstream& out, t_field* tfield, string prefix = "", bool is_element = false, bool is_propertyless = false);
-    void generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix = "");
-    void generate_serialize_container(ofstream& out, t_type* ttype, string prefix = "");
-    void generate_serialize_map_element(ofstream& out, t_map* tmap, string iter, string map);
-    void generate_serialize_set_element(ofstream& out, t_set* tmap, string iter);
-    void generate_serialize_list_element(ofstream& out, t_list* tlist, string iter);
-    void generate_netcore_doc(ofstream& out, t_field* field);
-    void generate_netcore_doc(ofstream& out, t_doc* tdoc);
-    void generate_netcore_doc(ofstream& out, t_function* tdoc);
-    void generate_netcore_docstring_comment(ofstream& out, string contents);
-    void docstring_comment(ofstream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end);
-    void start_netcore_namespace(ofstream& out);
-    void end_netcore_namespace(ofstream& out);
-
-    string netcore_type_usings() const;
-    string netcore_thrift_usings() const;
-    string type_name(t_type* ttype, bool in_countainer = false, bool in_init = false, bool in_param = false, bool is_required = false);
-    string base_type_name(t_base_type* tbase, bool in_container = false, bool in_param = false, bool is_required = false);
-    string declare_field(t_field* tfield, bool init = false, string prefix = "");
-    string function_signature_async(t_function* tfunction, string prefix = "");
-    string function_signature(t_function* tfunction, string prefix = "");
-    string argument_list(t_struct* tstruct);
-    string type_to_enum(t_type* ttype);
-    string prop_name(t_field* tfield, bool suppress_mapping = false);
-    string get_enum_class_name(t_type* type);
-
-    static string correct_function_name_for_async(string const& function_name)
+/**
+* \brief Search and replace "_args" substring in struct name if exist (for C# class naming)
+* \param struct_name
+* \return Modified struct name ("Struct_args" -> "StructArgs") or original name
+*/
+static string check_and_correct_struct_name(const string& struct_name)
+{
+    string args_end = "_args";
+    size_t i = struct_name.find(args_end);
+    if (i != string::npos)
     {
-        string const async_end = "Async";
-        size_t i = function_name.find(async_end);
-        if (i != string::npos)
-        {
-            return function_name + async_end;
-        }
-
-        return function_name;
+        string new_struct_name = struct_name;
+        new_struct_name.replace(i, args_end.length(), "Args");
+        return new_struct_name;
     }
 
-    /**
-     * \brief Search and replace "_args" substring in struct name if exist (for C# class naming)
-     * \param struct_name
-     * \return Modified struct name ("Struct_args" -> "StructArgs") or original name
-     */
-    static string check_and_correct_struct_name(const string& struct_name)
+    string result_end = "_result";
+    size_t j = struct_name.find(result_end);
+    if (j != string::npos)
     {
-        string args_end = "_args";
-        size_t i = struct_name.find(args_end);
-        if (i != string::npos)
-        {
-            string new_struct_name = struct_name;
-            new_struct_name.replace(i, args_end.length(), "Args");
-            return new_struct_name;
-        }
-
-        string result_end = "_result";
-        size_t j = struct_name.find(result_end);
-        if (j != string::npos)
-        {
-            string new_struct_name = struct_name;
-            new_struct_name.replace(j, result_end.length(), "Result");
-            return new_struct_name;
-        }
-
-        return struct_name;
+        string new_struct_name = struct_name;
+        new_struct_name.replace(j, result_end.length(), "Result");
+        return new_struct_name;
     }
 
-    static bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; }
+    return struct_name;
+}
 
-    static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; }
+static bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; }
 
-    static bool type_can_be_null(t_type* ttype)
+static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; }
+
+static bool type_can_be_null(t_type* ttype)
+{
+    while (ttype->is_typedef())
     {
-        while (ttype->is_typedef())
-        {
-            ttype = static_cast<t_typedef*>(ttype)->get_type();
-        }
-
-        return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string();
+        ttype = static_cast<t_typedef*>(ttype)->get_type();
     }
 
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string();
+}
 
-private:
-    string namespace_name_;
-    string namespace_dir_;
+bool t_netcore_generator::is_wcf_enabled() const { return wcf_; }
 
-    bool nullable_;
-    bool union_;
-    bool hashcode_;
-    bool serialize_;
-    bool wcf_;
+bool t_netcore_generator::is_nullable_enabled() const { return nullable_; }
 
-    string wcf_namespace_;
-    map<string, int> netcore_keywords;
-    vector<member_mapping_scope> member_mapping_scopes;
+bool t_netcore_generator::is_hashcode_enabled() const { return hashcode_; }
 
-    void init_keywords();
-    string normalize_name(string name);
-    string make_valid_csharp_identifier(string const& fromName);
-    void prepare_member_name_mapping(t_struct* tstruct);
-    void prepare_member_name_mapping(void* scope, const vector<t_field*>& members, const string& structname);
-    void cleanup_member_name_mapping(void* scope);
-    string get_mapped_member_name(string oldname);
-};
+bool t_netcore_generator::is_serialize_enabled() const { return serialize_; }
+
+bool t_netcore_generator::is_union_enabled() const { return union_; }
+
+map<string, int> t_netcore_generator::get_keywords_list() const
+{
+    return netcore_keywords;
+}
 
 void t_netcore_generator::init_generator()
 {
@@ -414,9 +328,11 @@
     netcore_keywords["var"] = 1;
     netcore_keywords["where"] = 1;
     netcore_keywords["yield"] = 1;
+
+	netcore_keywords["when"] = 1;
 }
 
-void t_netcore_generator::start_netcore_namespace(ofstream& out)
+void t_netcore_generator::start_netcore_namespace(ostream& out)
 {
     if (!namespace_name_.empty())
     {
@@ -425,7 +341,7 @@
     }
 }
 
-void t_netcore_generator::end_netcore_namespace(ofstream& out)
+void t_netcore_generator::end_netcore_namespace(ostream& out)
 {
     if (!namespace_name_.empty())
     {
@@ -479,35 +395,40 @@
 
 void t_netcore_generator::generate_enum(t_enum* tenum)
 {
-    int ic = indent_count();
-
+	int ic = indent_count();
     string f_enum_name = namespace_dir_ + "/" + tenum->get_name() + ".cs";
 
-    ofstream f_enum;
+    ofstream_with_content_based_conditional_update f_enum;
     f_enum.open(f_enum_name.c_str());
-    f_enum << autogen_comment() << endl;
 
-    start_netcore_namespace(f_enum);
-    generate_netcore_doc(f_enum, tenum);
+	generate_enum(f_enum, tenum);
 
-    f_enum << indent() << "public enum " << tenum->get_name() << endl;
-    scope_up(f_enum);
-
-    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)
-    {
-        generate_netcore_doc(f_enum, *c_iter);
-        int value = (*c_iter)->get_value();
-        f_enum << indent() << (*c_iter)->get_name() << " = " << value << "," << endl;
-    }
-
-    scope_down(f_enum);
-    end_netcore_namespace(f_enum);
     f_enum.close();
+	indent_validate(ic, "generate_enum");
+}
 
-    indent_validate(ic, "generate_enum");
+void t_netcore_generator::generate_enum(ostream& out, t_enum* tenum)
+{
+	out << autogen_comment() << endl;
+
+	start_netcore_namespace(out);
+	generate_netcore_doc(out, tenum);
+
+	out << indent() << "public enum " << tenum->get_name() << endl;
+	scope_up(out);
+
+	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)
+	{
+		generate_netcore_doc(out, *c_iter);
+		int value = (*c_iter)->get_value();
+		out << indent() << (*c_iter)->get_name() << " = " << value << "," << endl;
+	}
+
+	scope_down(out);
+	end_netcore_namespace(out);
 }
 
 void t_netcore_generator::generate_consts(vector<t_const*> consts)
@@ -518,23 +439,35 @@
     }
 
     string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs";
-    ofstream f_consts;
+    ofstream_with_content_based_conditional_update f_consts;
     f_consts.open(f_consts_name.c_str());
 
-    f_consts << autogen_comment() << netcore_type_usings() << endl;
+    generate_consts(f_consts, consts);
 
-    start_netcore_namespace(f_consts);
+    f_consts.close();
+}
 
-    f_consts << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Constants" << endl;
+void t_netcore_generator::generate_consts(ostream& out, vector<t_const*> consts)
+{
+    if (consts.empty())
+    {
+        return;
+    }
 
-    scope_up(f_consts);
+    out << autogen_comment() << netcore_type_usings() << endl;
+
+    start_netcore_namespace(out);
+
+    out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Constants" << endl;
+
+    scope_up(out);
 
     vector<t_const*>::iterator c_iter;
     bool need_static_constructor = false;
     for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter)
     {
-        generate_netcore_doc(f_consts, *c_iter);
-        if (print_const_value(f_consts, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false))
+        generate_netcore_doc(out, *c_iter);
+        if (print_const_value(out, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false))
         {
             need_static_constructor = true;
         }
@@ -542,28 +475,27 @@
 
     if (need_static_constructor)
     {
-        print_const_constructor(f_consts, consts);
+        print_const_constructor(out, consts);
     }
 
-    scope_down(f_consts);
-    end_netcore_namespace(f_consts);
-    f_consts.close();
+    scope_down(out);
+    end_netcore_namespace(out);
 }
 
-void t_netcore_generator::print_const_def_value(ofstream& out, string name, t_type* type, t_const_value* value)
+void t_netcore_generator::print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value)
 {
     if (type->is_struct() || type->is_xception())
     {
         const vector<t_field*>& fields = static_cast<t_struct*>(type)->get_members();
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
+        const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
         vector<t_field*>::const_iterator f_iter;
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
         prepare_member_name_mapping(static_cast<t_struct*>(type));
 
         for (v_iter = val.begin(); v_iter != val.end(); ++v_iter)
         {
             t_field* field = NULL;
-            
+
             for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
             {
                 if ((*f_iter)->get_name() == v_iter->first->get_string())
@@ -578,7 +510,7 @@
             }
 
             t_type* field_type = field->get_type();
-            
+
             string val = render_const_value(out, name, field_type, v_iter->second);
             out << indent() << name << "." << prop_name(field) << " = " << val << ";" << endl;
         }
@@ -589,8 +521,8 @@
     {
         t_type* ktype = static_cast<t_map*>(type)->get_key_type();
         t_type* vtype = static_cast<t_map*>(type)->get_val_type();
-        const map<t_const_value*, t_const_value*>& val = value->get_map();
-        map<t_const_value*, t_const_value*>::const_iterator v_iter;
+        const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+        map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
         for (v_iter = val.begin(); v_iter != val.end(); ++v_iter)
         {
             string key = render_const_value(out, name, ktype, v_iter->first);
@@ -620,7 +552,7 @@
     }
 }
 
-void t_netcore_generator::print_const_constructor(ofstream& out, vector<t_const*> consts)
+void t_netcore_generator::print_const_constructor(ostream& out, vector<t_const*> consts)
 {
     out << indent() << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" << endl;
     scope_up(out);
@@ -637,7 +569,7 @@
     scope_down(out);
 }
 
-bool t_netcore_generator::print_const_value(ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval, bool needtype)
+bool t_netcore_generator::print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval, bool needtype)
 {
     out << indent();
     bool need_static_construction = !in_static;
@@ -654,7 +586,7 @@
     if (type->is_base_type())
     {
         string v2 = render_const_value(out, name, type, value);
-        out << name << " = " << v2 << ";" << endl;
+        out << normalize_name(name) << " = " << v2 << ";" << endl;
         need_static_construction = false;
     }
     else if (type->is_enum())
@@ -683,7 +615,7 @@
     return need_static_construction;
 }
 
-string t_netcore_generator::render_const_value(ofstream& out, string name, t_type* type, t_const_value* value)
+string t_netcore_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value)
 {
     (void)name;
     ostringstream render;
@@ -755,7 +687,7 @@
     int ic = indent_count();
 
     string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs";
-    ofstream f_struct;
+    ofstream_with_content_based_conditional_update f_struct;
 
     f_struct.open(f_struct_name.c_str());
 
@@ -768,7 +700,7 @@
     indent_validate(ic, "generate_netcore_struct");
 }
 
-void t_netcore_generator::generate_netcore_struct_definition(ofstream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result)
+void t_netcore_generator::generate_netcore_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result)
 {
     if (!in_class)
     {
@@ -791,7 +723,7 @@
 
     out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : ";
 
-    if (is_exception) 
+    if (is_exception)
     {
         out << "TException, ";
     }
@@ -854,7 +786,7 @@
         out << indent() << "public struct Isset" << endl
             << indent() << "{" << endl;
         indent_up();
-        
+
         for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
         {
             bool is_required = field_is_required((*m_iter));
@@ -980,7 +912,7 @@
         generate_netcore_struct_hashcode(out, tstruct);
     }
     generate_netcore_struct_tostring(out, tstruct);
-    
+
     indent_down();
     out << indent() << "}" << endl << endl;
 
@@ -997,7 +929,7 @@
     }
 }
 
-void t_netcore_generator::generate_netcore_wcffault(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_wcffault(ostream& out, t_struct* tstruct)
 {
     out << endl;
     out << indent() << "[DataContract]" << endl;
@@ -1027,7 +959,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_reader(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_reader(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public async Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl
         << indent() << "{" << endl;
@@ -1036,7 +968,7 @@
         << indent() << "try" << endl
         << indent() << "{" << endl;
     indent_up();
-    
+
     const vector<t_field*>& fields = tstruct->get_members();
     vector<t_field*>::const_iterator f_iter;
 
@@ -1049,7 +981,7 @@
         }
     }
 
-    out << indent() << "TField field;" << endl 
+    out << indent() << "TField field;" << endl
         << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl
         << indent() << "while (true)" << endl
         << indent() << "{" << endl;
@@ -1064,7 +996,7 @@
         << indent() << "switch (field.ID)" << endl
         << indent() << "{" << endl;
     indent_up();
-    
+
     for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
     {
         bool is_required = field_is_required(*f_iter);
@@ -1118,7 +1050,7 @@
             out << indent() << "}" << endl;
         }
     }
-    
+
     indent_down();
     out << indent() << "}" << endl;
     out << indent() << "finally" << endl
@@ -1131,7 +1063,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_writer(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_writer(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl
         << indent() << "{" << endl;
@@ -1208,14 +1140,14 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_result_writer(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_result_writer(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl
         << indent() << "{" << endl;
     indent_up();
 
     out << indent() << "oprot.IncrementRecursionDepth();" << endl
-        << indent() << "try" << endl 
+        << indent() << "try" << endl
         << indent() << "{" << endl;
     indent_up();
 
@@ -1296,7 +1228,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_tostring(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_tostring(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public override string ToString()" << endl
         << indent() << "{" << endl;
@@ -1392,7 +1324,7 @@
     int ic = indent_count();
 
     string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs";
-    ofstream f_union;
+    ofstream_with_content_based_conditional_update f_union;
 
     f_union.open(f_union_name.c_str());
 
@@ -1401,11 +1333,11 @@
     generate_netcore_union_definition(f_union, tunion);
 
     f_union.close();
-    
+
     indent_validate(ic, "generate_netcore_union.");
 }
 
-void t_netcore_generator::generate_netcore_union_definition(ofstream& out, t_struct* tunion)
+void t_netcore_generator::generate_netcore_union_definition(ostream& out, t_struct* tunion)
 {
     // Let's define the class first
     start_netcore_namespace(out);
@@ -1414,7 +1346,7 @@
         << indent() << "{" << endl;
     indent_up();
 
-    out << indent() << "public abstract void Write(TProtocol protocol);" << endl
+    out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl
         << indent() << "public readonly bool Isset;" << endl
         << indent() << "public abstract object Data { get; }" << endl
         << indent() << "protected " << tunion->get_name() << "(bool isset)" << endl
@@ -1431,7 +1363,7 @@
     out << indent() << "public override object Data { get { return null; } }" << endl
         << indent() << "public ___undefined() : base(false) {}" << endl << endl;
 
-    out << indent() << "public override void Write(TProtocol protocol)" << endl
+    out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl
         << indent() << "{" << endl;
     indent_up();
     out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << endl;
@@ -1456,7 +1388,7 @@
     end_netcore_namespace(out);
 }
 
-void t_netcore_generator::generate_netcore_union_class(ofstream& out, t_struct* tunion, t_field* tfield)
+void t_netcore_generator::generate_netcore_union_class(ostream& out, t_struct* tunion, t_field* tfield)
 {
     out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl
         << indent() << "{" << endl;
@@ -1491,8 +1423,8 @@
     generate_serialize_field(out, tfield, "_data", true, true);
 
     out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl
-        << indent() << "await oprot.WriteFieldStop(cancellationToken);" << endl
-        << indent() << "await oprot.WriteStructEnd(cancellationToken);" << endl;
+        << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl
+        << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl;
     indent_down();
     out << indent() << "}" << endl
         << indent() << "finally" << endl
@@ -1506,12 +1438,12 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_equals(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_equals(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public override bool Equals(object that)" << endl
         << indent() << "{" << endl;
     indent_up();
-    out << indent() << "var other = that as " << type_name(tstruct) << ";" << endl
+    out << indent() << "var other = that as " << check_and_correct_struct_name(normalize_name(tstruct->get_name())) << ";" << endl
         << indent() << "if (other == null) return false;" << endl
         << indent() << "if (ReferenceEquals(this, other)) return true;" << endl;
 
@@ -1568,7 +1500,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_struct_hashcode(ofstream& out, t_struct* tstruct)
+void t_netcore_generator::generate_netcore_struct_hashcode(ostream& out, t_struct* tstruct)
 {
     out << indent() << "public override int GetHashCode() {" << endl;
     indent_up();
@@ -1620,7 +1552,7 @@
     int ic = indent_count();
 
     string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs";
-    ofstream f_service;
+    ofstream_with_content_based_conditional_update f_service;
     f_service.open(f_service_name.c_str());
 
     f_service << autogen_comment() << netcore_type_usings() << netcore_thrift_usings() << endl;
@@ -1645,7 +1577,7 @@
     indent_validate(ic, "generate_service.");
 }
 
-void t_netcore_generator::generate_service_interface(ofstream& out, t_service* tservice)
+void t_netcore_generator::generate_service_interface(ostream& out, t_service* tservice)
 {
     string extends = "";
     string extends_iface = "";
@@ -1693,7 +1625,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_service_helpers(ofstream& out, t_service* tservice)
+void t_netcore_generator::generate_service_helpers(ostream& out, t_service* tservice)
 {
     vector<t_function*> functions = tservice->get_functions();
     vector<t_function*>::iterator f_iter;
@@ -1706,7 +1638,7 @@
     }
 }
 
-void t_netcore_generator::generate_service_client(ofstream& out, t_service* tservice)
+void t_netcore_generator::generate_service_client(ostream& out, t_service* tservice)
 {
     string extends = "";
     string extends_client = "";
@@ -1788,7 +1720,7 @@
                 << indent() << "throw x;" << endl;
             indent_down();
 
-            out << indent() << "}" << endl 
+            out << indent() << "}" << endl
                 << endl
                 << indent() << "var result = new " << resultname << "();" << endl
                 << indent() << "await result.ReadAsync(InputProtocol, cancellationToken);" << endl
@@ -1809,7 +1741,7 @@
                     }
                     else
                     {
-                        out << indent() << "if (result.Success.HasValue)" << endl 
+                        out << indent() << "if (result.Success.HasValue)" << endl
                             << indent() << "{" << endl;
                         indent_up();
                         out << indent() << "return result.Success.Value;" << endl;
@@ -1877,7 +1809,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_service_server(ofstream& out, t_service* tservice)
+void t_netcore_generator::generate_service_server(ostream& out, t_service* tservice)
 {
     vector<t_function*> functions = tservice->get_functions();
     vector<t_function*>::iterator f_iter;
@@ -1895,7 +1827,7 @@
 
     indent_up();
 
-    out << indent() << "private IAsync _iAsync;" << endl 
+    out << indent() << "private IAsync _iAsync;" << endl
         << endl
         << indent() << "public AsyncProcessor(IAsync iAsync)";
 
@@ -1907,7 +1839,7 @@
     out << endl
         << indent() << "{" << endl;
     indent_up();
-    
+
     out << indent() << "if (iAsync == null) throw new ArgumentNullException(nameof(iAsync));" << endl
         << endl
         << indent() << "_iAsync = iAsync;" << endl;
@@ -2005,7 +1937,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_function_helpers(ofstream& out, t_function* tfunction)
+void t_netcore_generator::generate_function_helpers(ostream& out, t_function* tfunction)
 {
     if (tfunction->is_oneway())
     {
@@ -2030,10 +1962,10 @@
     generate_netcore_struct_definition(out, &result, false, true, true);
 }
 
-void t_netcore_generator::generate_process_function_async(ofstream& out, t_service* tservice, t_function* tfunction)
+void t_netcore_generator::generate_process_function_async(ostream& out, t_service* tservice, t_function* tfunction)
 {
     (void)tservice;
-    out << indent() << "public async Task " << tfunction->get_name() 
+    out << indent() << "public async Task " << tfunction->get_name()
         << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl
         << indent() << "{" << endl;
     indent_up();
@@ -2097,7 +2029,7 @@
     }
 
     cleanup_member_name_mapping(arg_struct);
-    
+
     if (!first)
     {
         out << ", ";
@@ -2112,7 +2044,7 @@
     {
         indent_down();
         out << indent() << "}" << endl;
-        
+
         for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter)
         {
             out << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ")" << endl
@@ -2130,7 +2062,7 @@
 
     if (!tfunction->is_oneway())
     {
-        out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" 
+        out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\""
                 << correct_function_name_for_async(tfunction->get_name()) << "\", TMessageType.Reply, seqid), cancellationToken); " << endl
             << indent() << "await result.WriteAsync(oprot, cancellationToken);" << endl;
     }
@@ -2172,13 +2104,13 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_netcore_union_reader(ofstream& out, t_struct* tunion)
+void t_netcore_generator::generate_netcore_union_reader(ostream& out, t_struct* tunion)
 {
     // Thanks to THRIFT-1768, we don't need to check for required fields in the union
     const vector<t_field*>& fields = tunion->get_members();
     vector<t_field*>::const_iterator f_iter;
 
-    out << indent() << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl;
+    out << indent() << "public static async Task<" << tunion->get_name() << "> ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl;
     scope_up(out);
 
     out << indent() << "iprot.IncrementRecursionDepth();" << endl;
@@ -2186,12 +2118,12 @@
     scope_up(out);
 
     out << indent() << tunion->get_name() << " retval;" << endl;
-    out << indent() << "iprot.ReadStructBegin();" << endl;
-    out << indent() << "TField field = iprot.ReadFieldBegin();" << endl;
+    out << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl;
+    out << indent() << "TField field = await iprot.ReadFieldBeginAsync(cancellationToken);" << endl;
     // we cannot have the first field be a stop -- we must have a single field defined
     out << indent() << "if (field.Type == TType.Stop)" << endl;
     scope_up(out);
-    out << indent() << "iprot.ReadFieldEnd();" << endl;
+    out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl;
     out << indent() << "retval = new ___undefined();" << endl;
     scope_down(out);
     out << indent() << "else" << endl;
@@ -2211,7 +2143,7 @@
         out << indent() << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl;
 
         indent_down();
-        out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
+        out << indent() << "} else { " << endl << indent() << " await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);"
             << endl << indent() << "  retval = new ___undefined();" << endl << indent() << "}" << endl
             << indent() << "break;" << endl;
         indent_down();
@@ -2219,23 +2151,23 @@
 
     out << indent() << "default: " << endl;
     indent_up();
-    out << indent() << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent()
+    out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl << indent()
         << "retval = new ___undefined();" << endl;
     out << indent() << "break;" << endl;
     indent_down();
 
     scope_down(out);
 
-    out << indent() << "iprot.ReadFieldEnd();" << endl;
+    out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl;
 
-    out << indent() << "if (iprot.ReadFieldBegin().Type != TType.Stop)" << endl;
+    out << indent() << "if ((await iprot.ReadFieldBeginAsync(cancellationToken)).Type != TType.Stop)" << endl;
     scope_up(out);
     out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl;
     scope_down(out);
 
     // end of else for TStop
     scope_down(out);
-    out << indent() << "iprot.ReadStructEnd();" << endl;
+    out << indent() << "await iprot.ReadStructEndAsync(cancellationToken);" << endl;
     out << indent() << "return retval;" << endl;
     indent_down();
 
@@ -2248,7 +2180,7 @@
     out << indent() << "}" << endl << endl;
 }
 
-void t_netcore_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix, bool is_propertyless)
+void t_netcore_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless)
 {
     t_type* type = tfield->get_type();
     while (type->is_typedef())
@@ -2334,7 +2266,7 @@
     }
 }
 
-void t_netcore_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix)
+void t_netcore_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix)
 {
     if (union_ && tstruct->is_union())
     {
@@ -2342,12 +2274,12 @@
     }
     else
     {
-        out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl 
+        out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl
             << indent() << "await " << prefix << ".ReadAsync(iprot, cancellationToken);" << endl;
     }
 }
 
-void t_netcore_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix)
+void t_netcore_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix)
 {
     out << indent() << "{" << endl;
     indent_up();
@@ -2419,7 +2351,7 @@
     out << indent() << "}" << endl;
 }
 
-void t_netcore_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix)
+void t_netcore_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix)
 {
     string key = tmp("_key");
     string val = tmp("_val");
@@ -2436,7 +2368,7 @@
     out << indent() << prefix << "[" << key << "] = " << val << ";" << endl;
 }
 
-void t_netcore_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix)
+void t_netcore_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix)
 {
     string elem = tmp("_elem");
     t_field felem(tset->get_elem_type(), elem);
@@ -2448,7 +2380,7 @@
     out << indent() << prefix << ".Add(" << elem << ");" << endl;
 }
 
-void t_netcore_generator::generate_deserialize_list_element(ofstream& out, t_list* tlist, string prefix)
+void t_netcore_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix)
 {
     string elem = tmp("_elem");
     t_field felem(tlist->get_elem_type(), elem);
@@ -2460,7 +2392,7 @@
     out << indent() << prefix << ".Add(" << elem << ");" << endl;
 }
 
-void t_netcore_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix, bool is_element, bool is_propertyless)
+void t_netcore_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool is_element, bool is_propertyless)
 {
     t_type* type = tfield->get_type();
     while (type->is_typedef())
@@ -2541,13 +2473,13 @@
     }
 }
 
-void t_netcore_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix)
+void t_netcore_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix)
 {
     (void)tstruct;
     out << indent() << "await " << prefix << ".WriteAsync(oprot, cancellationToken);" << endl;
 }
 
-void t_netcore_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix)
+void t_netcore_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix)
 {
     out << indent() << "{" << endl;
     indent_up();
@@ -2624,7 +2556,7 @@
     out << indent() << "}" << endl;
 }
 
-void t_netcore_generator::generate_serialize_map_element(ofstream& out, t_map* tmap, string iter, string map)
+void t_netcore_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map)
 {
     t_field kfield(tmap->get_key_type(), iter);
     generate_serialize_field(out, &kfield, "", true);
@@ -2632,24 +2564,24 @@
     generate_serialize_field(out, &vfield, "", true);
 }
 
-void t_netcore_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter)
+void t_netcore_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter)
 {
     t_field efield(tset->get_elem_type(), iter);
     generate_serialize_field(out, &efield, "", true);
 }
 
-void t_netcore_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter)
+void t_netcore_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter)
 {
     t_field efield(tlist->get_elem_type(), iter);
     generate_serialize_field(out, &efield, "", true);
 }
 
-void t_netcore_generator::generate_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset)
+void t_netcore_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset)
 {
     generate_netcore_property(out, tfield, isPublic, generateIsset, "_");
 }
 
-void t_netcore_generator::generate_netcore_property(ofstream& out, t_field* tfield, bool isPublic, bool generateIsset, string fieldPrefix)
+void t_netcore_generator::generate_netcore_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset, string fieldPrefix)
 {
     if ((serialize_ || wcf_) && isPublic)
     {
@@ -2788,9 +2720,7 @@
 void t_netcore_generator::prepare_member_name_mapping(void* scope, const vector<t_field*>& members, const string& structname)
 {
     // begin new scope
-    member_mapping_scope dummy;
-    dummy.scope_member = 0;
-    member_mapping_scopes.push_back(dummy);
+    member_mapping_scopes.push_back(member_mapping_scope());
     member_mapping_scope& active = member_mapping_scopes.back();
     active.scope_member = scope;
 
@@ -2936,7 +2866,7 @@
         }
         if (ttype->is_base_type() && field_has_default(tfield))
         {
-            ofstream dummy;
+            std::ofstream dummy;
             result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
         }
         else if (ttype->is_base_type())
@@ -3081,12 +3011,12 @@
     throw "INVALID TYPE IN type_to_enum: " + type->get_name();
 }
 
-void t_netcore_generator::generate_netcore_docstring_comment(ofstream& out, string contents)
+void t_netcore_generator::generate_netcore_docstring_comment(ostream& out, string contents)
 {
     docstring_comment(out, "/// <summary>" + endl, "/// ", contents, "/// </summary>" + endl);
 }
 
-void t_netcore_generator::generate_netcore_doc(ofstream& out, t_field* field)
+void t_netcore_generator::generate_netcore_doc(ostream& out, t_field* field)
 {
     if (field->get_type()->is_enum())
     {
@@ -3099,7 +3029,7 @@
     }
 }
 
-void t_netcore_generator::generate_netcore_doc(ofstream& out, t_doc* tdoc)
+void t_netcore_generator::generate_netcore_doc(ostream& out, t_doc* tdoc)
 {
     if (tdoc->has_doc())
     {
@@ -3107,7 +3037,7 @@
     }
 }
 
-void t_netcore_generator::generate_netcore_doc(ofstream& out, t_function* tfunction)
+void t_netcore_generator::generate_netcore_doc(ostream& out, t_function* tfunction)
 {
     if (tfunction->has_doc())
     {
@@ -3135,7 +3065,7 @@
     }
 }
 
-void t_netcore_generator::docstring_comment(ofstream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end)
+void t_netcore_generator::docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end)
 {
     if (comment_start != "")
     {
@@ -3144,17 +3074,17 @@
 
     stringstream docs(contents, std::ios_base::in);
 
-    while (!(docs.eof() || docs.fail())) 
+    while (!(docs.eof() || docs.fail()))
     {
         char line[1024];
         docs.getline(line, 1024);
 
         // Just prnt a newline when the line & prefix are empty.
-        if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) 
+        if (strlen(line) == 0 && line_prefix == "" && !docs.eof())
         {
             out << endl;
         }
-        else if (strlen(line) > 0 || !docs.eof()) 
+        else if (strlen(line) > 0 || !docs.eof())
         { // skip the empty last line
             out << indent() << line_prefix << line << endl;
         }
diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.h b/compiler/cpp/src/thrift/generate/t_netcore_generator.h
new file mode 100644
index 0000000..6efc922
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.h
@@ -0,0 +1,137 @@
+#include <cassert>
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+class t_netcore_generator : public t_oop_generator
+{
+
+    struct member_mapping_scope
+    {
+    public:
+        member_mapping_scope() : scope_member(0) { }
+        void* scope_member;
+        map<string, string> mapping_table;
+    };
+
+public:
+    t_netcore_generator(t_program* program, const map<string, string>& parsed_options, const string& option_string);
+
+    bool is_wcf_enabled() const;
+    bool is_nullable_enabled() const;
+    bool is_hashcode_enabled() const;
+    bool is_serialize_enabled() const;
+    bool is_union_enabled() const;
+    map<string, int> get_keywords_list() const;
+
+    // overrides
+    void init_generator();
+    void close_generator();
+    void generate_consts(vector<t_const*> consts);
+    void generate_consts(ostream& out, vector<t_const*> consts);
+    void generate_typedef(t_typedef* ttypedef);
+    void generate_enum(t_enum* tenum);
+    void generate_enum(ostream& out, t_enum* tenum);
+    void generate_struct(t_struct* tstruct);
+    void generate_xception(t_struct* txception);
+    void generate_service(t_service* tservice);
+
+    void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset);
+    void generate_netcore_property(ostream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = "");
+    bool print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false);
+    string render_const_value(ostream& out, string name, t_type* type, t_const_value* value);
+    void print_const_constructor(ostream& out, vector<t_const*> consts);
+    void print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value);
+    void generate_netcore_struct(t_struct* tstruct, bool is_exception);
+    void generate_netcore_union(t_struct* tunion);
+    void generate_netcore_struct_definition(ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false);
+    void generate_netcore_union_definition(ostream& out, t_struct* tunion);
+    void generate_netcore_union_class(ostream& out, t_struct* tunion, t_field* tfield);
+    void generate_netcore_wcffault(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_reader(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_result_writer(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_writer(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_tostring(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_equals(ostream& out, t_struct* tstruct);
+    void generate_netcore_struct_hashcode(ostream& out, t_struct* tstruct);
+    void generate_netcore_union_reader(ostream& out, t_struct* tunion);
+    void generate_function_helpers(ostream& out, t_function* tfunction);
+    void generate_service_interface(ostream& out, t_service* tservice);
+    void generate_service_helpers(ostream& out, t_service* tservice);
+    void generate_service_client(ostream& out, t_service* tservice);
+    void generate_service_server(ostream& out, t_service* tservice);
+    void generate_process_function_async(ostream& out, t_service* tservice, t_function* function);
+    void generate_deserialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_propertyless = false);
+    void generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix = "");
+    void generate_deserialize_container(ostream& out, t_type* ttype, string prefix = "");
+    void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix = "");
+    void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix = "");
+    void generate_deserialize_list_element(ostream& out, t_list* list, string prefix = "");
+    void generate_serialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_element = false, bool is_propertyless = false);
+    void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix = "");
+    void generate_serialize_container(ostream& out, t_type* ttype, string prefix = "");
+    void generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map);
+    void generate_serialize_set_element(ostream& out, t_set* tmap, string iter);
+    void generate_serialize_list_element(ostream& out, t_list* tlist, string iter);
+    void generate_netcore_doc(ostream& out, t_field* field);
+    void generate_netcore_doc(ostream& out, t_doc* tdoc);
+    void generate_netcore_doc(ostream& out, t_function* tdoc);
+    void generate_netcore_docstring_comment(ostream& out, string contents);
+    void docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end);
+    void start_netcore_namespace(ostream& out);
+    void end_netcore_namespace(ostream& out);
+
+    string netcore_type_usings() const;
+    string netcore_thrift_usings() const;
+
+    string type_name(t_type* ttype, bool in_countainer = false, bool in_init = false, bool in_param = false, bool is_required = false);
+    string base_type_name(t_base_type* tbase, bool in_container = false, bool in_param = false, bool is_required = false);
+    string declare_field(t_field* tfield, bool init = false, string prefix = "");
+    string function_signature_async(t_function* tfunction, string prefix = "");
+    string function_signature(t_function* tfunction, string prefix = "");
+    string argument_list(t_struct* tstruct);
+    string type_to_enum(t_type* ttype);
+    string prop_name(t_field* tfield, bool suppress_mapping = false);
+    string get_enum_class_name(t_type* type);
+
+private:
+    string namespace_name_;
+    string namespace_dir_;
+
+    bool nullable_;
+    bool union_;
+    bool hashcode_;
+    bool serialize_;
+    bool wcf_;
+
+    string wcf_namespace_;
+    map<string, int> netcore_keywords;
+    vector<member_mapping_scope> member_mapping_scopes;
+
+    void init_keywords();
+    string normalize_name(string name);
+    string make_valid_csharp_identifier(string const& fromName);
+    void prepare_member_name_mapping(t_struct* tstruct);
+    void prepare_member_name_mapping(void* scope, const vector<t_field*>& members, const string& structname);
+    void cleanup_member_name_mapping(void* scope);
+    string get_mapped_member_name(string oldname);
+};
diff --git a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
index 594219a..0ec81ba 100644
--- a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc
@@ -32,7 +32,7 @@
 
 using std::ios;
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -90,16 +90,16 @@
    */
 
   void generate_ocaml_struct(t_struct* tstruct, bool is_exception);
-  void generate_ocaml_struct_definition(std::ofstream& out,
+  void generate_ocaml_struct_definition(std::ostream& out,
                                         t_struct* tstruct,
                                         bool is_xception = false);
-  void generate_ocaml_struct_member(std::ofstream& out, string tname, t_field* tmember);
-  void generate_ocaml_struct_sig(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_ocaml_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_ocaml_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_ocaml_struct_member(std::ostream& out, string tname, t_field* tmember);
+  void generate_ocaml_struct_sig(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_ocaml_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_ocaml_struct_writer(std::ostream& out, t_struct* tstruct);
   void generate_ocaml_function_helpers(t_function* tfunction);
-  void generate_ocaml_method_copy(std::ofstream& out, const vector<t_field*>& members);
-  void generate_ocaml_member_copy(std::ofstream& out, t_field* member);
+  void generate_ocaml_method_copy(std::ostream& out, const vector<t_field*>& members);
+  void generate_ocaml_member_copy(std::ostream& out, t_field* member);
 
   /**
    * Service-level generation functions
@@ -115,33 +115,33 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out, t_field* tfield, std::string prefix);
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct);
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct);
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype);
+  void generate_deserialize_container(std::ostream& out, t_type* ttype);
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset);
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset);
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
-  void generate_deserialize_type(std::ofstream& out, t_type* type);
+  void generate_deserialize_type(std::ostream& out, t_type* type);
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string name = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string name = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
   /**
    * Helper rendering functions
@@ -161,12 +161,12 @@
    * File streams
    */
 
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_consts_;
+  ofstream_with_content_based_conditional_update f_service_;
 
-  std::ofstream f_types_i_;
-  std::ofstream f_service_i_;
+  ofstream_with_content_based_conditional_update f_types_i_;
+  ofstream_with_content_based_conditional_update f_service_i_;
 };
 
 /*
@@ -401,8 +401,8 @@
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -425,8 +425,8 @@
   } else if (type->is_map()) {
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     string hm = tmp("_hm");
     out << endl;
     indent_up();
@@ -499,7 +499,7 @@
   generate_ocaml_struct_sig(f_types_i_, tstruct, is_exception);
 }
 
-void t_ocaml_generator::generate_ocaml_method_copy(ofstream& out, const vector<t_field*>& members) {
+void t_ocaml_generator::generate_ocaml_method_copy(ostream& out, const vector<t_field*>& members) {
   vector<t_field*>::const_iterator m_iter;
 
   /* Create a copy of the current object */
@@ -555,7 +555,7 @@
   return what;
 }
 
-void t_ocaml_generator::generate_ocaml_member_copy(ofstream& out, t_field* tmember) {
+void t_ocaml_generator::generate_ocaml_member_copy(ostream& out, t_field* tmember) {
   string mname = decapitalize(tmember->get_name());
   t_type* type = get_true_type(tmember->get_type());
 
@@ -576,7 +576,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_ocaml_generator::generate_ocaml_struct_definition(ofstream& out,
+void t_ocaml_generator::generate_ocaml_struct_definition(ostream& out,
                                                          t_struct* tstruct,
                                                          bool is_exception) {
   const vector<t_field*>& members = tstruct->get_members();
@@ -611,7 +611,7 @@
  * @param tname Name of the parent structure for the member
  * @param tmember Member definition
  */
-void t_ocaml_generator::generate_ocaml_struct_member(ofstream& out,
+void t_ocaml_generator::generate_ocaml_struct_member(ostream& out,
                                                      string tname,
                                                      t_field* tmember) {
   string x = tmp("_x");
@@ -713,7 +713,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_ocaml_generator::generate_ocaml_struct_sig(ofstream& out,
+void t_ocaml_generator::generate_ocaml_struct_sig(ostream& out,
                                                   t_struct* tstruct,
                                                   bool is_exception) {
   const vector<t_field*>& members = tstruct->get_members();
@@ -752,7 +752,7 @@
 /**
  * Generates the read method for a struct
  */
-void t_ocaml_generator::generate_ocaml_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_ocaml_generator::generate_ocaml_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
   string sname = type_name(tstruct);
@@ -812,7 +812,7 @@
   indent_down();
 }
 
-void t_ocaml_generator::generate_ocaml_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_ocaml_generator::generate_ocaml_struct_writer(ostream& out, t_struct* tstruct) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_sorted_members();
   vector<t_field*>::const_iterator f_iter;
@@ -1309,7 +1309,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_ocaml_generator::generate_deserialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_ocaml_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = tfield->get_type();
 
   string name = decapitalize(tfield->get_name());
@@ -1321,7 +1321,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_ocaml_generator::generate_deserialize_type(ofstream& out, t_type* type) {
+void t_ocaml_generator::generate_deserialize_type(ostream& out, t_type* type) {
   type = get_true_type(type);
 
   if (type->is_void()) {
@@ -1374,7 +1374,7 @@
 /**
  * Generates an unserializer for a struct, calling read()
  */
-void t_ocaml_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct) {
+void t_ocaml_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct) {
   string prefix = "";
   t_program* program = tstruct->get_program();
   if (program != NULL && program != program_) {
@@ -1388,7 +1388,7 @@
  * Serialize a container by writing out the header followed by
  * data and then a footer.
  */
-void t_ocaml_generator::generate_deserialize_container(ofstream& out, t_type* ttype) {
+void t_ocaml_generator::generate_deserialize_container(ostream& out, t_type* ttype) {
   string size = tmp("_size");
   string ktype = tmp("_ktype");
   string vtype = tmp("_vtype");
@@ -1454,7 +1454,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_ocaml_generator::generate_serialize_field(ofstream& out, t_field* tfield, string name) {
+void t_ocaml_generator::generate_serialize_field(ostream& out, t_field* tfield, string name) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -1523,12 +1523,12 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_ocaml_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_ocaml_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << prefix << "#write(oprot)";
 }
 
-void t_ocaml_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_ocaml_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   if (ttype->is_map()) {
     indent(out) << "oprot#writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ",";
     out << type_to_enum(((t_map*)ttype)->get_val_type()) << ",";
@@ -1579,7 +1579,7 @@
  * Serializes the members of a map.
  *
  */
-void t_ocaml_generator::generate_serialize_map_element(ofstream& out,
+void t_ocaml_generator::generate_serialize_map_element(ostream& out,
                                                        t_map* tmap,
                                                        string kiter,
                                                        string viter) {
@@ -1593,7 +1593,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_ocaml_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_ocaml_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
@@ -1601,7 +1601,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_ocaml_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_ocaml_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
diff --git a/compiler/cpp/src/thrift/generate/t_oop_generator.h b/compiler/cpp/src/thrift/generate/t_oop_generator.h
index 8fb580d..f8da547 100644
--- a/compiler/cpp/src/thrift/generate/t_oop_generator.h
+++ b/compiler/cpp/src/thrift/generate/t_oop_generator.h
@@ -65,11 +65,11 @@
     return package + type->get_name();
   }
 
-  virtual void generate_java_docstring_comment(std::ofstream& out, std::string contents) {
+  virtual void generate_java_docstring_comment(std::ostream& out, std::string contents) {
     generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
   }
 
-  virtual void generate_java_doc(std::ofstream& out, t_field* field) {
+  virtual void generate_java_doc(std::ostream& out, t_field* field) {
     if (field->get_type()->is_enum()) {
       std::string combined_message = field->get_doc() + "\n@see "
                                      + get_enum_class_name(field->get_type());
@@ -82,7 +82,7 @@
   /**
    * Emits a JavaDoc comment if the provided object has a doc in Thrift
    */
-  virtual void generate_java_doc(std::ofstream& out, t_doc* tdoc) {
+  virtual void generate_java_doc(std::ostream& out, t_doc* tdoc) {
     if (tdoc->has_doc()) {
       generate_java_docstring_comment(out, tdoc->get_doc());
     }
@@ -91,7 +91,7 @@
   /**
    * Emits a JavaDoc comment if the provided function object has a doc in Thrift
    */
-  virtual void generate_java_doc(std::ofstream& out, t_function* tfunction) {
+  virtual void generate_java_doc(std::ostream& out, t_function* tfunction) {
     if (tfunction->has_doc()) {
       std::stringstream ss;
       ss << tfunction->get_doc();
diff --git a/compiler/cpp/src/thrift/generate/t_perl_generator.cc b/compiler/cpp/src/thrift/generate/t_perl_generator.cc
index 0c05cda..8924a76 100644
--- a/compiler/cpp/src/thrift/generate/t_perl_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_perl_generator.cc
@@ -31,7 +31,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -87,11 +87,11 @@
    */
 
   void generate_perl_struct(t_struct* tstruct, bool is_exception);
-  void generate_perl_struct_definition(std::ofstream& out,
+  void generate_perl_struct_definition(std::ostream& out,
                                        t_struct* tstruct,
                                        bool is_xception = false);
-  void generate_perl_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_perl_struct_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_perl_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_perl_struct_writer(std::ostream& out, t_struct* tstruct);
   void generate_perl_function_helpers(t_function* tfunction);
 
   /**
@@ -110,37 +110,37 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   bool inclass = false);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
   /**
    * Helper rendering functions
@@ -208,10 +208,10 @@
   /**
    * File streams
    */
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_helpers_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_consts_;
+  ofstream_with_content_based_conditional_update f_helpers_;
+  ofstream_with_content_based_conditional_update f_service_;
 
   bool f_types_use_includes_emitted_;
 };
@@ -354,13 +354,13 @@
   } else if (type->is_enum()) {
     out << value->get_integer();
   } else if (type->is_struct() || type->is_xception()) {
-    out << "new " << perl_namespace(type->get_program()) << type->get_name() << "({" << endl;
+    out << perl_namespace(type->get_program()) << type->get_name() << "->new({" << endl;
     indent_up();
 
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -385,8 +385,8 @@
     out << "{" << endl;
     indent_up();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       indent(out) << render_const_value(ktype, v_iter->first);
       out << " => ";
@@ -453,7 +453,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_perl_generator::generate_perl_struct_definition(ofstream& out,
+void t_perl_generator::generate_perl_struct_definition(ostream& out,
                                                        t_struct* tstruct,
                                                        bool is_exception) {
   const vector<t_field*>& members = tstruct->get_members();
@@ -531,7 +531,7 @@
 /**
  * Generates the read() method for a struct
  */
-void t_perl_generator::generate_perl_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_perl_generator::generate_perl_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -546,7 +546,7 @@
   indent(out) << "$xfer += $input->readStructBegin(\\$fname);" << endl;
 
   // Loop over reading in fields
-  indent(out) << "while (1) " << endl;
+  indent(out) << "while (1)" << endl;
 
   scope_up(out);
 
@@ -601,7 +601,7 @@
 /**
  * Generates the write() method for a struct
  */
-void t_perl_generator::generate_perl_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_perl_generator::generate_perl_struct_writer(ostream& out, t_struct* tstruct) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_sorted_members();
   vector<t_field*>::const_iterator f_iter;
@@ -758,7 +758,7 @@
 
   f_service_ << indent() << "$input->skip(Thrift::TType::STRUCT);" << endl << indent()
              << "$input->readMessageEnd();" << endl << indent()
-             << "my $x = new Thrift::TApplicationException('Function '.$fname.' not implemented.', "
+             << "my $x = Thrift::TApplicationException->new('Function '.$fname.' not implemented.', "
                 "Thrift::TApplicationException::UNKNOWN_METHOD);" << endl << indent()
              << "$output->writeMessageBegin($fname, Thrift::TMessageType::EXCEPTION, $rseqid);" << endl
              << indent() << "$x->write($output);" << endl << indent()
@@ -798,7 +798,7 @@
   string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_"
                       + tfunction->get_name() + "_result";
 
-  f_service_ << indent() << "my $args = new " << argsname << "();" << endl << indent()
+  f_service_ << indent() << "my $args = " << argsname << "->new();" << endl << indent()
              << "$args->read($input);" << endl;
 
   f_service_ << indent() << "$input->readMessageEnd();" << endl;
@@ -809,7 +809,7 @@
 
   // Declare result for non oneway function
   if (!tfunction->is_oneway()) {
-    f_service_ << indent() << "my $result = new " << resultname << "();" << endl;
+    f_service_ << indent() << "my $result = " << resultname << "->new();" << endl;
   }
 
   // Try block for a function with exceptions
@@ -858,7 +858,7 @@
     f_service_ << indent() << "if ($@) {" << endl;
     indent_up();
     f_service_ << indent() << "$@ =~ s/^\\s+|\\s+$//g;" << endl
-               << indent() << "my $err = new Thrift::TApplicationException(\"Unexpected Exception: \" . $@, Thrift::TApplicationException::INTERNAL_ERROR);" << endl
+               << indent() << "my $err = Thrift::TApplicationException->new(\"Unexpected Exception: \" . $@, Thrift::TApplicationException::INTERNAL_ERROR);" << endl
                << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', Thrift::TMessageType::EXCEPTION, $seqid);" << endl
                << indent() << "$err->write($output);" << endl
                << indent() << "$output->writeMessageEnd();" << endl
@@ -1106,7 +1106,7 @@
                << "', " << ((*f_iter)->is_oneway() ? "Thrift::TMessageType::ONEWAY" : "Thrift::TMessageType::CALL")
                << ", $self->{seqid});" << endl;
 
-    f_service_ << indent() << "my $args = new " << argsname << "();" << endl;
+    f_service_ << indent() << "my $args = " << argsname << "->new();" << endl;
 
     for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
       f_service_ << indent() << "$args->{" << (*fld_iter)->get_name() << "} = $"
@@ -1140,12 +1140,12 @@
 
       f_service_ << indent() << "$self->{input}->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);"
                  << endl << indent() << "if ($mtype == Thrift::TMessageType::EXCEPTION) {" << endl
-                 << indent() << "  my $x = new Thrift::TApplicationException();" << endl << indent()
+                 << indent() << "  my $x = Thrift::TApplicationException->new();" << endl << indent()
                  << "  $x->read($self->{input});" << endl << indent()
                  << "  $self->{input}->readMessageEnd();" << endl << indent() << "  die $x;" << endl
                  << indent() << "}" << endl;
 
-      f_service_ << indent() << "my $result = new " << resultname << "();" << endl << indent()
+      f_service_ << indent() << "my $result = " << resultname << "->new();" << endl << indent()
                  << "$result->read($self->{input});" << endl;
 
       f_service_ << indent() << "$self->{input}->readMessageEnd();" << endl << endl;
@@ -1183,7 +1183,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_perl_generator::generate_deserialize_field(ofstream& out,
+void t_perl_generator::generate_deserialize_field(ostream& out,
                                                   t_field* tfield,
                                                   string prefix,
                                                   bool inclass) {
@@ -1256,7 +1256,7 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_perl_generator::generate_deserialize_struct(ofstream& out,
+void t_perl_generator::generate_deserialize_struct(ostream& out,
                                                    t_struct* tstruct,
                                                    string prefix) {
   out << indent() << "$" << prefix << " = " << perl_namespace(tstruct->get_program())
@@ -1264,7 +1264,7 @@
       << "->read($input);" << endl;
 }
 
-void t_perl_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_perl_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   string size = tmp("_size");
@@ -1332,7 +1332,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_perl_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_perl_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("key");
   string val = tmp("val");
   t_field fkey(tmap->get_key_type(), key);
@@ -1347,7 +1347,7 @@
   indent(out) << "$" << prefix << "->{$" << key << "} = $" << val << ";" << endl;
 }
 
-void t_perl_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_perl_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -1358,7 +1358,7 @@
   indent(out) << "$" << prefix << "->{$" << elem << "} = 1;" << endl;
 }
 
-void t_perl_generator::generate_deserialize_list_element(ofstream& out,
+void t_perl_generator::generate_deserialize_list_element(ostream& out,
                                                          t_list* tlist,
                                                          string prefix) {
   string elem = tmp("elem");
@@ -1377,7 +1377,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_perl_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_perl_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -1448,7 +1448,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_perl_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_perl_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
 }
@@ -1456,7 +1456,7 @@
 /**
  * Writes out a container
  */
-void t_perl_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_perl_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   scope_up(out);
 
   if (ttype->is_map()) {
@@ -1520,7 +1520,7 @@
  * Serializes the members of a map.
  *
  */
-void t_perl_generator::generate_serialize_map_element(ofstream& out,
+void t_perl_generator::generate_serialize_map_element(ostream& out,
                                                       t_map* tmap,
                                                       string kiter,
                                                       string viter) {
@@ -1534,7 +1534,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_perl_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_perl_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
@@ -1542,7 +1542,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_perl_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_perl_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield);
 }
@@ -1586,7 +1586,7 @@
       result += " = []";
     } else if (type->is_struct() || type->is_xception()) {
       if (obj) {
-        result += " = new " + perl_namespace(type->get_program()) + type->get_name() + "()";
+        result += " = " + perl_namespace(type->get_program()) + type->get_name() + "->new()";
       } else {
         result += " = undef";
       }
diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc
index 11771c2..50a4415 100644
--- a/compiler/cpp/src/thrift/generate/t_php_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc
@@ -29,7 +29,7 @@
 #include "thrift/generate/t_oop_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -62,7 +62,7 @@
     validate_ = false;
     json_serializable_ = false;
     nsglobal_ = ""; // by default global namespace is empty
-    psr4_ = false;
+    classmap_ = false;
     for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if (iter->first.compare("inlined") == 0) {
         binary_inline_ = true;
@@ -78,8 +78,14 @@
         json_serializable_ = true;
       } else if (iter->first.compare("nsglobal") == 0) {
         nsglobal_ = iter->second;
+      } else if (iter->first.compare("classmap") == 0) {
+        classmap_ = true;
       } else if (iter->first.compare("psr4") == 0) {
-        psr4_ = true;
+        if(classmap_){
+          throw "psr4 and classmap are mutually exclusive.";
+        } else {
+          pwarning(0, "psr4 is default option! needn't add psr4 option!\n");
+        }
       } else {
         throw "unknown option php:" + iter->first;
       }
@@ -93,6 +99,10 @@
     escape_['$'] = "\\$";
   }
 
+  virtual std::string indent_str() const {
+    return "    ";
+  }
+
   static bool is_valid_namespace(const std::string& sub_namespace);
 
   /**
@@ -120,26 +130,26 @@
    */
 
   void generate_php_struct(t_struct* tstruct, bool is_exception);
-  void generate_php_struct_definition(std::ofstream& out,
+  void generate_php_struct_definition(std::ostream& out,
                                       t_struct* tstruct,
                                       bool is_xception = false,
                                       bool is_result = false);
-  void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct, bool is_result);
-  void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_php_struct_reader(std::ostream& out, t_struct* tstruct, bool is_result);
+  void generate_php_struct_writer(std::ostream& out, t_struct* tstruct, bool is_result);
   void generate_php_function_helpers(t_service* tservice, t_function* tfunction);
-  void generate_php_struct_required_validator(ofstream& out,
+  void generate_php_struct_required_validator(ostream& out,
                                               t_struct* tstruct,
                                               std::string method_name,
                                               bool write_mode);
-  void generate_php_struct_read_validator(ofstream& out, t_struct* tstruct);
-  void generate_php_struct_write_validator(ofstream& out, t_struct* tstruct);
-  void generate_php_struct_json_serialize(ofstream& out, t_struct* tstruct, bool is_result);
+  void generate_php_struct_read_validator(ostream& out, t_struct* tstruct);
+  void generate_php_struct_write_validator(ostream& out, t_struct* tstruct);
+  void generate_php_struct_json_serialize(ostream& out, t_struct* tstruct, bool is_result);
   bool needs_php_write_validator(t_struct* tstruct, bool is_result);
   bool needs_php_read_validator(t_struct* tstruct, bool is_result);
   int get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode);
 
-  void generate_php_type_spec(std::ofstream& out, t_type* t);
-  void generate_php_struct_spec(std::ofstream& out, t_struct* tstruct);
+  void generate_php_type_spec(std::ostream& out, t_type* t);
+  void generate_php_struct_spec(std::ostream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
@@ -150,53 +160,53 @@
   void generate_service_rest(t_service* tservice);
   void generate_service_client(t_service* tservice);
   void generate_service_processor(t_service* tservice);
-  void generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction);
-  void generate_service_header(t_service* tservice, std::ofstream& file);
-  void generate_program_header(std::ofstream& file);
+  void generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction);
+  void generate_service_header(t_service* tservice, std::ostream& file);
+  void generate_program_header(std::ostream& file);
 
   /**
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "",
                                   bool inclass = false);
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_php_doc(std::ofstream& out, t_doc* tdoc);
+  void generate_php_doc(std::ostream& out, t_doc* tdoc);
 
-  void generate_php_doc(std::ofstream& out, t_field* tfield);
+  void generate_php_doc(std::ostream& out, t_field* tfield);
 
-  void generate_php_doc(std::ofstream& out, t_function* tfunction);
+  void generate_php_doc(std::ostream& out, t_function* tfunction);
 
-  void generate_php_docstring_comment(std::ofstream& out, string contents);
+  void generate_php_docstring_comment(std::ostream& out, string contents);
 
   /**
    * Helper rendering functions
@@ -347,8 +357,8 @@
   /**
    * File streams
    */
-  std::ofstream f_types_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_service_;
 
   std::string package_dir_;
   /**
@@ -372,9 +382,9 @@
   bool oop_;
 
   /**
-   * Whether to hold each class in separate file to allow PSR4-autoloading
+   * Whether to generate old-style PHP file to use classmap autoloading
    */
-  bool psr4_;
+  bool classmap_;
 
   /**
    * Whether to generate validator code
@@ -415,8 +425,8 @@
     MKDIR(package_dir_.c_str());
   }
 
-  // Prepare output file for all the types in non-psr4 mode
-  if (!psr4_) {
+  // Prepare output file for all the types in classmap mode
+  if (classmap_) {
     // Make output file
     string f_types_name = package_dir_ + "Types.php";
     f_types_.open(f_types_name.c_str());
@@ -442,16 +452,15 @@
                 "use stdClass;\n";
   }
 
-  return includes + "\n";
+  return includes;
 }
 
 /**
  * Close up (or down) some filez.
  */
 void t_php_generator::close_generator() {
-  if (!psr4_) {
+  if (classmap_) {
     // Close types file
-    f_types_ << endl;
     f_types_.close();
   }
 }
@@ -468,10 +477,11 @@
 /**
  * Generates service header contains namespace suffix and includes inside file specified
  */
-void t_php_generator::generate_service_header(t_service* tservice, std::ofstream& file) {
+void t_php_generator::generate_service_header(t_service* tservice, std::ostream& file) {
   file << "<?php" << endl;
   if (!php_namespace_suffix(tservice->get_program()).empty()) {
-    file << "namespace " << php_namespace_suffix(tservice->get_program()) << ";" << endl;
+    file << "namespace " << php_namespace_suffix(tservice->get_program()) << ";" << endl
+         << endl;
   }
   file << autogen_comment() << php_includes();
 
@@ -481,10 +491,11 @@
 /**
  * Generates program header contains namespace suffix and includes inside file specified
  */
-void t_php_generator::generate_program_header(std::ofstream& file) {
+void t_php_generator::generate_program_header(std::ostream& file) {
   file << "<?php" << endl;
   if (!php_namespace_suffix(get_program()).empty()) {
-    file << "namespace " << php_namespace_suffix(get_program()) << ";" << endl << endl;
+    file << "namespace " << php_namespace_suffix(get_program()) << ";" << endl
+         << endl;
   }
   file << autogen_comment() << php_includes();
 
@@ -498,8 +509,8 @@
  * @param tenum The enumeration
  */
 void t_php_generator::generate_enum(t_enum* tenum) {
-  std::ofstream& f_enum = f_types_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_enum = f_types_;
+  if (!classmap_) {
     string f_enum_name = package_dir_ + tenum->get_name() + ".php";
     f_enum.open(f_enum_name.c_str());
     generate_program_header(f_enum);
@@ -512,26 +523,31 @@
   // code but you can't do things like an 'extract' on it, which is a bit of
   // a downer.
   generate_php_doc(f_enum, tenum);
-  f_enum << "final class " << tenum->get_name() << " {" << endl;
+  f_enum << "final class " << tenum->get_name() << endl
+         << "{" << endl;
   indent_up();
 
   for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
     int value = (*c_iter)->get_value();
     generate_php_doc(f_enum, *c_iter);
-    indent(f_enum) << "const " << (*c_iter)->get_name() << " = " << value << ";" << endl;
+    indent(f_enum) << "const " << (*c_iter)->get_name() << " = " << value << ";" << endl
+                   << endl;
   }
 
   indent(f_enum) << "static public $__names = array(" << endl;
+
+  indent_up();
   for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
     int value = (*c_iter)->get_value();
-    indent(f_enum) << "  " << value << " => '" << (*c_iter)->get_name() << "'," << endl;
+    indent(f_enum) << value << " => '" << (*c_iter)->get_name() << "'," << endl;
   }
+  indent_down();
   indent(f_enum) << ");" << endl;
 
   indent_down();
 
   f_enum << "}" << endl << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_enum.close();
   }
 }
@@ -547,13 +563,14 @@
   // Create class only if needed
   if (consts.size() > 0) {
 
-    std::ofstream& f_consts = f_types_;
-    if (psr4_) {
+    ofstream_with_content_based_conditional_update& f_consts = f_types_;
+    if (!classmap_) {
       string f_consts_name = package_dir_ + "Constant.php";
       f_consts.open(f_consts_name.c_str());
       generate_program_header(f_consts);
     }
-    f_consts << "final class Constant extends \\Thrift\\Type\\TConstant {" << endl;
+    f_consts << "final class Constant extends \\Thrift\\Type\\TConstant"<< endl
+             << "{" << endl;
 
     indent_up();
 
@@ -570,7 +587,8 @@
 
       f_consts << endl;
 
-      indent(f_consts) << "static protected function init_" << name << "() {" << endl;
+      f_consts << indent() << "protected static function init_" << name << "()" <<endl
+               << indent() << "{" << endl;
       indent_up();
 
       indent(f_consts) << "return ";
@@ -583,8 +601,8 @@
     }
 
     indent_down();
-    f_consts << "}" << endl << endl;
-    if (psr4_) {
+    f_consts << "}" << endl;
+    if (!classmap_) {
       f_consts.close();
     }
   }
@@ -630,8 +648,8 @@
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -655,8 +673,8 @@
     t_type* vtype = ((t_map*)type)->get_val_type();
     out << "array(" << endl;
     indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       out << indent();
       out << render_const_value(ktype, v_iter->first);
@@ -712,19 +730,19 @@
  * Structs can be normal or exceptions.
  */
 void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) {
-  std::ofstream& f_struct = f_types_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_struct = f_types_;
+  if (!classmap_) {
     string f_struct_name = package_dir_ + tstruct->get_name() + ".php";
     f_struct.open(f_struct_name.c_str());
     generate_program_header(f_struct);
   }
   generate_php_struct_definition(f_struct, tstruct, is_exception);
-  if (psr4_) {
+  if (!classmap_) {
     f_struct.close();
   }
 }
 
-void t_php_generator::generate_php_type_spec(ofstream& out, t_type* t) {
+void t_php_generator::generate_php_type_spec(ostream& out, t_type* t) {
   t = get_true_type(t);
   indent(out) << "'type' => " << type_to_enum(t) << "," << endl;
 
@@ -770,8 +788,8 @@
  * Generates the struct specification structure, which fully qualifies enough
  * type information to generalize serialization routines.
  */
-void t_php_generator::generate_php_struct_spec(ofstream& out, t_struct* tstruct) {
-  indent(out) << "static $_TSPEC = array(" << endl;
+void t_php_generator::generate_php_struct_spec(ostream& out, t_struct* tstruct) {
+  indent(out) << "static public $_TSPEC = array(" << endl;
   indent_up();
 
   const vector<t_field*>& members = tstruct->get_members();
@@ -783,12 +801,12 @@
     out << indent() << "'var' => '" << (*m_iter)->get_name() << "'," << endl;
     out << indent() << "'isRequired' => " << ((*m_iter)->get_req() == t_field::T_REQUIRED ? "true" : "false") << "," << endl;
     generate_php_type_spec(out, t);
-    indent(out) << ")," << endl;
     indent_down();
+    indent(out) << ")," << endl;
   }
 
   indent_down();
-  indent(out) << "  );" << endl << endl;
+  indent(out) << ");" << endl << endl;
 }
 
 /**
@@ -798,7 +816,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_php_generator::generate_php_struct_definition(ofstream& out,
+void t_php_generator::generate_php_struct_definition(ostream& out,
                                                      t_struct* tstruct,
                                                      bool is_exception,
                                                      bool is_result) {
@@ -817,10 +835,11 @@
   if (json_serializable_) {
     out << " implements JsonSerializable";
   }
-  out << " {" << endl;
+  out << endl
+      << "{" << endl;
   indent_up();
 
-  out << indent() << "static $isValidate = " << (validate_ ? "true" : "false") << ";" << endl << endl;
+  out << indent() << "static public $isValidate = " << (validate_ ? "true" : "false") << ";" << endl << endl;
 
   generate_php_struct_spec(out, tstruct);
 
@@ -837,8 +856,9 @@
   out << endl;
 
   // Generate constructor from array
-  string param = (members.size() > 0) ? "$vals=null" : "";
-  out << indent() << "public function __construct(" << param << ") {" << endl;
+  string param = (members.size() > 0) ? "$vals = null" : "";
+  out << indent() << "public function __construct(" << param << ")"<< endl
+      << indent() << "{" << endl;
   indent_up();
 
   if (members.size() > 0) {
@@ -855,9 +875,14 @@
       out << indent() << "parent::__construct(self::$_TSPEC, $vals);" << endl;
     } else {
       for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        out << indent() << "if (isset($vals['" << (*m_iter)->get_name() << "'])) {" << endl
-            << indent() << "  $this->" << (*m_iter)->get_name() << " = $vals['"
-            << (*m_iter)->get_name() << "'];" << endl << indent() << "}" << endl;
+        out << indent() << "if (isset($vals['" << (*m_iter)->get_name() << "'])) {" << endl;
+
+        indent_up();
+        out << indent() << "$this->" << (*m_iter)->get_name() << " = $vals['"
+            << (*m_iter)->get_name() << "'];" << endl;
+
+        indent_down();
+        out << indent() << "}" << endl;
       }
     }
     indent_down();
@@ -866,29 +891,40 @@
   scope_down(out);
   out << endl;
 
-  out << indent() << "public function getName() {" << endl << indent() << "  return '"
-      << tstruct->get_name() << "';" << endl << indent() << "}" << endl << endl;
+  out << indent() << "public function getName()" << endl
+      << indent() << "{" << endl;
 
+  indent_up();
+  out << indent() << "return '" << tstruct->get_name() << "';" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+
+  out << endl;
   generate_php_struct_reader(out, tstruct, is_result);
+  out << endl;
   generate_php_struct_writer(out, tstruct, is_result);
   if (needs_php_read_validator(tstruct, is_result)) {
+    out << endl;
     generate_php_struct_read_validator(out, tstruct);
   }
   if (needs_php_write_validator(tstruct, is_result)) {
+    out << endl;
     generate_php_struct_write_validator(out, tstruct);
   }
   if (json_serializable_) {
+    out << endl;
     generate_php_struct_json_serialize(out, tstruct, is_result);
   }
 
   indent_down();
-  out << indent() << "}" << endl << endl;
+  out << indent() << "}" << endl;
 }
 
 /**
  * Generates the read() method for a struct
  */
-void t_php_generator::generate_php_struct_reader(ofstream& out, t_struct* tstruct, bool is_result) {
+void t_php_generator::generate_php_struct_reader(ostream& out, t_struct* tstruct, bool is_result) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -919,9 +955,9 @@
   }
 
   // Loop over reading in fields
-  indent(out) << "while (true)" << endl;
+  indent(out) << "while (true) {" << endl;
 
-  scope_up(out);
+  indent_up();
 
   // Read beginning field marker
   if (binary_inline_) {
@@ -943,9 +979,9 @@
   }
 
   // Switch statement on the field we are reading
-  indent(out) << "switch ($fid)" << endl;
+  indent(out) << "switch ($fid) {" << endl;
 
-  scope_up(out);
+  indent_up();
 
   // Generate deserialization code for known cases
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -956,25 +992,31 @@
     generate_deserialize_field(out, *f_iter, "this->");
     indent_down();
     out << indent() << "} else {" << endl;
+
+    indent_up();
     if (binary_inline_) {
-      indent(out) << "  $xfer += "
-                  << "TProtocol::skipBinary($input, $ftype);" << endl;
+      indent(out) << "$xfer += TProtocol::skipBinary($input, $ftype);" << endl;
     } else {
-      indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+      indent(out) << "$xfer += $input->skip($ftype);" << endl;
     }
+
+    indent_down();
     out << indent() << "}" << endl << indent() << "break;" << endl;
     indent_down();
   }
 
   // In the default case we skip the field
   indent(out) << "default:" << endl;
+
+  indent_up();
   if (binary_inline_) {
-    indent(out) << "  $xfer += "
+    indent(out) << "$xfer += "
                 << "TProtocol::skipBinary($input, $ftype);" << endl;
   } else {
-    indent(out) << "  $xfer += $input->skip($ftype);" << endl;
+    indent(out) << "$xfer += $input->skip($ftype);" << endl;
   }
-  indent(out) << "  break;" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
 
   scope_down(out);
 
@@ -996,22 +1038,23 @@
   indent(out) << "return $xfer;" << endl;
 
   indent_down();
-  out << indent() << "}" << endl << endl;
+  out << indent() << "}" << endl;
 }
 
 /**
  * Generates the write() method for a struct
  */
-void t_php_generator::generate_php_struct_writer(ofstream& out, t_struct* tstruct, bool is_result) {
+void t_php_generator::generate_php_struct_writer(ostream& out, t_struct* tstruct, bool is_result) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_sorted_members();
   vector<t_field*>::const_iterator f_iter;
 
   if (binary_inline_) {
-    indent(out) << "public function write(&$output) {" << endl;
+    indent(out) << "public function write(&$output)" << endl;
   } else {
-    indent(out) << "public function write($output) {" << endl;
+    indent(out) << "public function write($output)" << endl;
   }
+  indent(out) << "{" << endl;
   indent_up();
 
   if (needs_php_write_validator(tstruct, is_result)) {
@@ -1086,18 +1129,18 @@
   out << indent() << "return $xfer;" << endl;
 
   indent_down();
-  out << indent() << "}" << endl << endl;
+  out << indent() << "}" << endl;
 }
 
-void t_php_generator::generate_php_struct_read_validator(ofstream& out, t_struct* tstruct) {
+void t_php_generator::generate_php_struct_read_validator(ostream& out, t_struct* tstruct) {
   generate_php_struct_required_validator(out, tstruct, "_validateForRead", false);
 }
 
-void t_php_generator::generate_php_struct_write_validator(ofstream& out, t_struct* tstruct) {
+void t_php_generator::generate_php_struct_write_validator(ostream& out, t_struct* tstruct) {
   generate_php_struct_required_validator(out, tstruct, "_validateForWrite", true);
 }
 
-void t_php_generator::generate_php_struct_required_validator(ofstream& out,
+void t_php_generator::generate_php_struct_required_validator(ostream& out,
                                                              t_struct* tstruct,
                                                              std::string method_name,
                                                              bool write_mode) {
@@ -1124,10 +1167,10 @@
   }
 
   indent_down();
-  indent(out) << "}" << endl << endl;
+  indent(out) << "}" << endl;
 }
 
-void t_php_generator::generate_php_struct_json_serialize(ofstream& out,
+void t_php_generator::generate_php_struct_json_serialize(ostream& out,
                                                          t_struct* tstruct,
                                                          bool is_result) {
   indent(out) << "public function jsonSerialize() {" << endl;
@@ -1173,7 +1216,7 @@
   indent(out) << "return $json;" << endl;
   indent_down();
 
-  indent(out) << "}" << endl << endl;
+  indent(out) << "}" << endl;
 }
 
 int t_php_generator::get_php_num_required_fields(const vector<t_field*>& fields, bool write_mode) {
@@ -1207,7 +1250,7 @@
  * @param tservice The service definition
  */
 void t_php_generator::generate_service(t_service* tservice) {
-  if(!psr4_) {
+  if(classmap_) {
     string f_service_name = package_dir_ + service_name_ + ".php";
     f_service_.open(f_service_name.c_str());
     generate_service_header(tservice, f_service_);
@@ -1224,7 +1267,7 @@
     generate_service_processor(tservice);
   }
 
-  if(!psr4_) {
+  if(classmap_) {
     // Close service file
     f_service_ << endl;
     f_service_.close();
@@ -1237,8 +1280,8 @@
  * @param tservice The service to generate a server for.
  */
 void t_php_generator::generate_service_processor(t_service* tservice) {
-  std::ofstream& f_service_processor = f_service_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_service_processor = f_service_;
+  if (!classmap_) {
     string f_service_processor_name = package_dir_ + service_name_ + "Processor.php";
     f_service_processor.open(f_service_processor_name.c_str());
     generate_service_header(tservice, f_service_processor);
@@ -1257,23 +1300,30 @@
   }
 
   // Generate the header portion
-  f_service_processor << "class " << service_name_ << "Processor" << extends_processor << " {" << endl;
+  f_service_processor << "class " << service_name_ << "Processor" << extends_processor << endl
+                      << "{" << endl;
   indent_up();
 
   if (extends.empty()) {
     f_service_processor << indent() << "protected $handler_ = null;" << endl;
   }
 
-  f_service_processor << indent() << "public function __construct($handler) {" << endl;
+  f_service_processor << indent() << "public function __construct($handler)"<< endl
+                      << indent() << "{" << endl;
+
+  indent_up();
   if (extends.empty()) {
-    f_service_processor << indent() << "  $this->handler_ = $handler;" << endl;
+    f_service_processor << indent() << "$this->handler_ = $handler;" << endl;
   } else {
-    f_service_processor << indent() << "  parent::__construct($handler);" << endl;
+    f_service_processor << indent() << "parent::__construct($handler);" << endl;
   }
+
+  indent_down();
   f_service_processor << indent() << "}" << endl << endl;
 
   // Generate the server implementation
-  indent(f_service_processor) << "public function process($input, $output) {" << endl;
+  f_service_processor << indent() << "public function process($input, $output)" << endl
+                      << indent() << "{" << endl;
   indent_up();
 
   f_service_processor << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
@@ -1291,11 +1341,12 @@
   }
 
   // HOT: check for method implementation
-  f_service_processor << indent() << "$methodname = 'process_'.$fname;" << endl << indent()
-                      << "if (!method_exists($this, $methodname)) {" << endl;
+  f_service_processor << indent() << "$methodname = 'process_'.$fname;" << endl
+                      << indent() << "if (!method_exists($this, $methodname)) {" << endl;
+
+  indent_up();
   if (binary_inline_) {
-    f_service_processor << indent() << "  throw new \\Exception('Function '.$fname.' not implemented.');"
-                        << endl;
+    f_service_processor << indent() << "throw new \\Exception('Function '.$fname.' not implemented.');" << endl;
   } else {
     f_service_processor << indent() << "  $input->skip("
                         << "TType::STRUCT);" << endl << indent() << "  $input->readMessageEnd();" << endl
@@ -1308,9 +1359,12 @@
                         << endl << indent() << "  $output->getTransport()->flush();" << endl << indent()
                         << "  return;" << endl;
   }
-  f_service_processor << indent() << "}" << endl << indent()
-                      << "$this->$methodname($rseqid, $input, $output);" << endl << indent()
-                      << "return true;" << endl;
+
+  indent_down();
+  f_service_processor << indent() << "}" << endl
+                      << indent() << "$this->$methodname($rseqid, $input, $output);" << endl
+                      << indent() << "return true;" << endl;
+
   indent_down();
   f_service_processor << indent() << "}" << endl << endl;
 
@@ -1322,7 +1376,7 @@
   indent_down();
   f_service_processor << "}" << endl;
 
-  if (psr4_) {
+  if (!classmap_) {
     f_service_processor.close();
   }
 }
@@ -1332,10 +1386,10 @@
  *
  * @param tfunction The function to write a dispatcher for
  */
-void t_php_generator::generate_process_function(std::ofstream& out, t_service* tservice, t_function* tfunction) {
+void t_php_generator::generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction) {
   // Open function
-  indent(out) << "protected function process_" << tfunction->get_name()
-                     << "($seqid, $input, $output) {" << endl;
+  out << indent() << "protected function process_" << tfunction->get_name() << "($seqid, $input, $output)" << endl
+      << indent() << "{" << endl;
   indent_up();
 
   string argsname = php_namespace(tservice->get_program()) + service_name_ + "_"
@@ -1346,21 +1400,32 @@
   out << indent() << "$bin_accel = ($input instanceof "
              << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary_after_message_begin');"
              << endl;
-  out << indent() << "if ($bin_accel)" << endl;
-  scope_up(out);
+  out << indent() << "if ($bin_accel) {" << endl;
+  indent_up();
 
-  out << indent() << "$args = thrift_protocol_read_binary_after_message_begin($input, '" << argsname
-             << "', $input->isStrictRead());" << endl;
+  out << indent() << "$args = thrift_protocol_read_binary_after_message_begin(" <<endl;
 
-  scope_down(out);
-  out << indent() << "else" << endl;
-  scope_up(out);
-  out << indent() << "$args = new " << argsname << "();" << endl << indent()
-             << "$args->read($input);" << endl;
+  indent_up();
+  out << indent() << "$input,"<<endl
+      << indent() << "'" << argsname << "'," << endl
+      << indent() << "$input->isStrictRead()" <<endl;
+
+  indent_down();
+  out << indent() <<");" << endl;
+
+  indent_down();
+  out << indent() << "} else {" << endl;
+
+  indent_up();
+  out << indent() << "$args = new " << argsname << "();" << endl
+      << indent() << "$args->read($input);" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl;
+
   if (!binary_inline_) {
     out << indent() << "$input->readMessageEnd();" << endl;
   }
-  scope_down(out);
 
   t_struct* xs = tfunction->get_xceptions();
   const std::vector<t_field*>& xceptions = xs->get_members();
@@ -1428,16 +1493,25 @@
              << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
              << endl;
 
-  out << indent() << "if ($bin_accel)" << endl;
-  scope_up(out);
+  out << indent() << "if ($bin_accel) {" << endl;
+  indent_up();
 
-  out << indent() << "thrift_protocol_write_binary($output, '" << tfunction->get_name()
-             << "', "
-             << "TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());" << endl;
+  out << indent() << "thrift_protocol_write_binary(" << endl;
 
-  scope_down(out);
-  out << indent() << "else" << endl;
-  scope_up(out);
+  indent_up();
+  out << indent() << "$output,"<<endl
+      << indent() << "'" << tfunction->get_name()<< "'," <<endl
+      << indent() << "TMessageType::REPLY,"<< endl
+      << indent() << "$result," << endl
+      << indent() << "$seqid," << endl
+      << indent() << "$output->isStrictWrite()"<<endl;
+
+  indent_down();
+  out << indent() << ");" << endl;
+
+  indent_down();
+  out << indent() << "} else {" << endl;
+  indent_up();
 
   // Serialize the request header
   if (binary_inline_) {
@@ -1470,8 +1544,8 @@
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
 
-  std::ofstream& f_struct_definition = f_service_;
-  if (!psr4_) {
+  ofstream_with_content_based_conditional_update& f_struct_definition = f_service_;
+  if (classmap_) {
     f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
   }
 
@@ -1480,14 +1554,14 @@
     string name = ts->get_name();
     ts->set_name(service_name_ + "_" + name);
 
-    if (psr4_) {
+    if (!classmap_) {
       string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php";
       f_struct_definition.open(f_struct_definition_name.c_str());
       generate_service_header(tservice, f_struct_definition);
     }
 
     generate_php_struct_definition(f_struct_definition, ts);
-    if (psr4_) {
+    if (!classmap_) {
       f_struct_definition.close();
     }
 
@@ -1516,14 +1590,14 @@
       result.append(*f_iter);
     }
 
-    std::ofstream& f_struct_helper = f_service_;
-    if (psr4_) {
+    ofstream_with_content_based_conditional_update& f_struct_helper = f_service_;
+    if (!classmap_) {
       string f_struct_helper_name = package_dir_ + result.get_name() + ".php";
       f_struct_helper.open(f_struct_helper_name.c_str());
       generate_service_header(tservice, f_struct_helper);
     }
     generate_php_struct_definition(f_struct_helper, &result, false, true);
-    if (psr4_) {
+    if (!classmap_) {
       f_struct_helper.close();
     }
   }
@@ -1535,8 +1609,8 @@
  * @param tservice The service to generate a header definition for
  */
 void t_php_generator::generate_service_interface(t_service* tservice) {
-  std::ofstream& f_service_interface = f_service_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_service_interface = f_service_;
+  if (!classmap_) {
     string f_service_interface_name = package_dir_ + service_name_ + "If.php";
     f_service_interface.open(f_service_interface_name.c_str());
     generate_service_header(tservice, f_service_interface);
@@ -1551,8 +1625,9 @@
                  + tservice->get_extends()->get_name() + "If";
   }
   generate_php_doc(f_service_interface, tservice);
-  f_service_interface << "interface " << php_namespace_declaration(tservice) << "If" << extends_if << " {"
-             << endl;
+  f_service_interface << "interface " << php_namespace_declaration(tservice) << "If" << extends_if << endl
+                      << "{" << endl;
+
   indent_up();
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
@@ -1561,11 +1636,10 @@
     indent(f_service_interface) << "public function " << function_signature(*f_iter) << ";" << endl;
   }
   indent_down();
-  f_service_interface << "}" << endl << endl;
+  f_service_interface << "}" << endl;
 
   // Close service interface file
-  f_service_interface << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_service_interface.close();
   }
 }
@@ -1574,8 +1648,8 @@
  * Generates a REST interface
  */
 void t_php_generator::generate_service_rest(t_service* tservice) {
-  std::ofstream& f_service_rest = f_service_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_service_rest = f_service_;
+  if (!classmap_) {
     string f_service_rest_name = package_dir_ + service_name_ + "Rest.php";
     f_service_rest.open(f_service_rest_name.c_str());
     generate_service_header(tservice, f_service_rest);
@@ -1589,7 +1663,8 @@
     extends_if = " extends " + php_namespace(tservice->get_extends()->get_program())
                  + tservice->get_extends()->get_name() + "Rest";
   }
-  f_service_rest << "class " << service_name_ << "Rest" << extends_if << " {" << endl;
+  f_service_rest << "class " << service_name_ << "Rest" << extends_if << endl
+                 << "{" << endl;
   indent_up();
 
   if (extends.empty()) {
@@ -1643,7 +1718,7 @@
 
   // Close service rest file
   f_service_rest << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_service_rest.close();
   }
 }
@@ -1654,8 +1729,8 @@
  * @param tservice The service to generate a server for.
  */
 void t_php_generator::generate_service_client(t_service* tservice) {
-  std::ofstream& f_service_client = f_service_;
-  if (psr4_) {
+  ofstream_with_content_based_conditional_update& f_service_client = f_service_;
+  if (!classmap_) {
     string f_service_client_name = package_dir_ + service_name_ + "Client.php";
     f_service_client.open(f_service_client_name.c_str());
     generate_service_header(tservice, f_service_client);
@@ -1670,8 +1745,8 @@
   }
 
   f_service_client << "class " << php_namespace_declaration(tservice) << "Client" << extends_client
-             << " implements " << php_namespace(tservice->get_program()) << service_name_ << "If {"
-             << endl;
+             << " implements " << php_namespace(tservice->get_program()) << service_name_ << "If" << endl
+             <<"{"<< endl;
   indent_up();
 
   // Private members
@@ -1682,13 +1757,18 @@
   }
 
   // Constructor function
-  f_service_client << indent() << "public function __construct($input, $output=null) {" << endl;
+  f_service_client << indent() << "public function __construct($input, $output = null)" << endl
+                   << indent() << "{" << endl;
+
+  indent_up();
   if (!extends.empty()) {
-    f_service_client << indent() << "  parent::__construct($input, $output);" << endl;
+    f_service_client << indent() << "parent::__construct($input, $output);" << endl;
   } else {
-    f_service_client << indent() << "  $this->input_ = $input;" << endl << indent()
-               << "  $this->output_ = $output ? $output : $input;" << endl;
+    f_service_client << indent() << "$this->input_ = $input;" << endl
+                     << indent() << "$this->output_ = $output ? $output : $input;" << endl;
   }
+
+  indent_down();
   f_service_client << indent() << "}" << endl << endl;
 
   // Generate client method implementations
@@ -1700,6 +1780,8 @@
     vector<t_field*>::const_iterator fld_iter;
     string funname = (*f_iter)->get_name();
 
+    f_service_client << endl;
+
     // Open function
     indent(f_service_client) << "public function " << function_signature(*f_iter) << endl;
     scope_up(f_service_client);
@@ -1743,18 +1825,27 @@
                << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');"
                << endl;
 
-    f_service_client << indent() << "if ($bin_accel)" << endl;
-    scope_up(f_service_client);
+    f_service_client << indent() << "if ($bin_accel) {" << endl;
+    indent_up();
 
     string messageType = (*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL";
 
-    f_service_client << indent() << "thrift_protocol_write_binary($this->output_, '"
-               << (*f_iter)->get_name() << "', " << messageType
-               << ", $args, $this->seqid_, $this->output_->isStrictWrite());" << endl;
+    f_service_client << indent() << "thrift_protocol_write_binary(" << endl;
 
-    scope_down(f_service_client);
-    f_service_client << indent() << "else" << endl;
-    scope_up(f_service_client);
+    indent_up();
+    f_service_client << indent() << "$this->output_," << endl
+               << indent() << "'" << (*f_iter)->get_name() << "'," << endl
+               << indent() << messageType << "," << endl
+               << indent() << "$args," << endl
+               << indent() << "$this->seqid_," << endl
+               << indent() << "$this->output_->isStrictWrite()" << endl;
+
+    indent_down();
+    f_service_client << indent() << ");" << endl;
+
+    indent_down();
+    f_service_client << indent() << "} else {" << endl;
+    indent_up();
 
     // Serialize the request header
     if (binary_inline_) {
@@ -1799,14 +1890,26 @@
                        << "TBinaryProtocolAccelerated)"
                        << " && function_exists('thrift_protocol_read_binary');" << endl;
 
-      f_service_client << indent()
-                       << "if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '"
-                       << resultname << "', $this->input_->isStrictRead());" << endl;
-      f_service_client << indent() << "else" << endl;
-      scope_up(f_service_client);
+      f_service_client << indent() << "if ($bin_accel) {" << endl;
 
-      f_service_client << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl
-                 << indent() << "$mtype = 0;" << endl << endl;
+      indent_up();
+      f_service_client << indent() << "$result = thrift_protocol_read_binary(" << endl;
+
+      indent_up();
+      f_service_client << indent() << "$this->input_," << endl
+                       << indent() << "'" << resultname << "'," << endl
+                       << indent() << "$this->input_->isStrictRead()" << endl;
+
+      indent_down();
+      f_service_client << indent() << ");" << endl;
+
+      indent_down();
+      f_service_client << indent() << "} else {" << endl;
+
+      indent_up();
+      f_service_client << indent() << "$rseqid = 0;" << endl
+                       << indent() << "$fname = null;" << endl
+                       << indent() << "$mtype = 0;" << endl << endl;
 
       if (binary_inline_) {
         t_field ffname(g_type_string, "fname");
@@ -1820,16 +1923,20 @@
         generate_deserialize_field(f_service_client, &ffname, "", true);
         generate_deserialize_field(f_service_client, &fseqid, "", true);
       } else {
-        f_service_client << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);"
-                         << endl << indent() << "if ($mtype == "
-                         << "TMessageType::EXCEPTION) {" << endl << indent() << "  $x = new "
-                         << "TApplicationException();" << endl << indent() << "  $x->read($this->input_);"
-                         << endl << indent() << "  $this->input_->readMessageEnd();" << endl << indent()
-                         << "  throw $x;" << endl << indent() << "}" << endl;
+        f_service_client << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);" << endl
+                         << indent() << "if ($mtype == TMessageType::EXCEPTION) {" << endl;
+
+        indent_up();
+        f_service_client << indent() << "$x = new TApplicationException();" << endl
+                         << indent() << "$x->read($this->input_);" << endl
+                         << indent() << "$this->input_->readMessageEnd();" << endl
+                         << indent() << "throw $x;" << endl;
+        indent_down();
+        f_service_client << indent() << "}" << endl;
       }
 
-      f_service_client << indent() << "$result = new " << resultname << "();" << endl << indent()
-                       << "$result->read($this->input_);" << endl;
+      f_service_client << indent() << "$result = new " << resultname << "();" << endl
+                       << indent() << "$result->read($this->input_);" << endl;
 
       if (!binary_inline_) {
         f_service_client << indent() << "$this->input_->readMessageEnd();" << endl;
@@ -1839,17 +1946,26 @@
 
       // Careful, only return result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_client << indent() << "if ($result->success !== null) {" << endl << indent()
-                   << "  return $result->success;" << endl << indent() << "}" << endl;
+        f_service_client << indent() << "if ($result->success !== null) {" << endl;
+
+        indent_up();
+        f_service_client << indent() << "return $result->success;" << endl;
+
+        indent_down();
+        f_service_client << indent() << "}" << endl;
       }
 
       t_struct* xs = (*f_iter)->get_xceptions();
       const std::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) {
-        f_service_client << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl
-                         << indent() << "  throw $result->" << (*x_iter)->get_name() << ";" << endl
-                         << indent() << "}" << endl;
+        f_service_client << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl;
+
+        indent_up();
+        f_service_client << indent() << "throw $result->" << (*x_iter)->get_name() << ";" << endl;
+
+        indent_down();
+        f_service_client << indent() << "}" << endl;
       }
 
       // Careful, only return _result if not a void function
@@ -1862,16 +1978,14 @@
 
       // Close function
       scope_down(f_service_client);
-      f_service_client << endl;
     }
   }
 
   indent_down();
-  f_service_client << "}" << endl << endl;
+  f_service_client << "}" << endl;
 
   // Close service client file
-  f_service_client << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_service_client.close();
   }
 }
@@ -1879,7 +1993,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_php_generator::generate_deserialize_field(ofstream& out,
+void t_php_generator::generate_deserialize_field(ostream& out,
                                                  t_field* tfield,
                                                  string prefix,
                                                  bool inclass) {
@@ -2011,13 +2125,13 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_php_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_php_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   out << indent() << "$" << prefix << " = new " << php_namespace(tstruct->get_program())
       << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix
       << "->read($input);" << endl;
 }
 
-void t_php_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_php_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   string size = tmp("_size");
   string ktype = tmp("_ktype");
   string vtype = tmp("_vtype");
@@ -2065,9 +2179,9 @@
 
   // For loop iterates over elements
   string i = tmp("_i");
-  indent(out) << "for ($" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")" << endl;
+  indent(out) << "for ($" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ") {" << endl;
 
-  scope_up(out);
+  indent_up();
 
   if (ttype->is_map()) {
     generate_deserialize_map_element(out, (t_map*)ttype, prefix);
@@ -2094,7 +2208,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_php_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_php_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("key");
   string val = tmp("val");
   t_field fkey(tmap->get_key_type(), key);
@@ -2109,7 +2223,7 @@
   indent(out) << "$" << prefix << "[$" << key << "] = $" << val << ";" << endl;
 }
 
-void t_php_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_php_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -2125,7 +2239,7 @@
   }
 }
 
-void t_php_generator::generate_deserialize_list_element(ofstream& out,
+void t_php_generator::generate_deserialize_list_element(ostream& out,
                                                         t_list* tlist,
                                                         string prefix) {
   string elem = tmp("elem");
@@ -2144,7 +2258,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_php_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_php_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2249,7 +2363,7 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_php_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_php_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << "$xfer += $" << prefix << "->write($output);" << endl;
 }
@@ -2257,9 +2371,7 @@
 /**
  * Writes out a container
  */
-void t_php_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
-  scope_up(out);
-
+void t_php_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   if (ttype->is_map()) {
     if (binary_inline_) {
       out << indent() << "$output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type())
@@ -2295,21 +2407,19 @@
     }
   }
 
-  scope_up(out);
-
   if (ttype->is_map()) {
     string kiter = tmp("kiter");
     string viter = tmp("viter");
     indent(out) << "foreach ($" << prefix << " as "
-                << "$" << kiter << " => $" << viter << ")" << endl;
-    scope_up(out);
+                << "$" << kiter << " => $" << viter << ") {" << endl;
+    indent_up();
     generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
     scope_down(out);
   } else if (ttype->is_set()) {
     string iter = tmp("iter");
     string iter_val = tmp("iter");
-    indent(out) << "foreach ($" << prefix << " as $" << iter << " => $" << iter_val << ")" << endl;
-    scope_up(out);
+    indent(out) << "foreach ($" << prefix << " as $" << iter << " => $" << iter_val << ") {" << endl;
+    indent_up();
 
     t_type* elem_type = ((t_set*)ttype)->get_elem_type();
     if(php_is_scalar(elem_type)) {
@@ -2320,14 +2430,12 @@
     scope_down(out);
   } else if (ttype->is_list()) {
     string iter = tmp("iter");
-    indent(out) << "foreach ($" << prefix << " as $" << iter << ")" << endl;
-    scope_up(out);
+    indent(out) << "foreach ($" << prefix << " as $" << iter << ") {" << endl;
+    indent_up();
     generate_serialize_list_element(out, (t_list*)ttype, iter);
     scope_down(out);
   }
 
-  scope_down(out);
-
   if (!binary_inline_) {
     if (ttype->is_map()) {
       indent(out) << "$output->writeMapEnd();" << endl;
@@ -2337,15 +2445,13 @@
       indent(out) << "$output->writeListEnd();" << endl;
     }
   }
-
-  scope_down(out);
 }
 
 /**
  * Serializes the members of a map.
  *
  */
-void t_php_generator::generate_serialize_map_element(ofstream& out,
+void t_php_generator::generate_serialize_map_element(ostream& out,
                                                      t_map* tmap,
                                                      string kiter,
                                                      string viter) {
@@ -2359,7 +2465,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_php_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_php_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2367,7 +2473,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_php_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_php_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2375,14 +2481,14 @@
 /**
  * Emits a PHPDoc comment for the given contents
  */
-void t_php_generator::generate_php_docstring_comment(ofstream& out, string contents) {
+void t_php_generator::generate_php_docstring_comment(ostream& out, string contents) {
   generate_docstring_comment(out, "/**\n", " * ", contents, " */\n");
 }
 
 /**
  * Emits a PHPDoc comment if the provided object has a doc in Thrift
  */
-void t_php_generator::generate_php_doc(ofstream& out, t_doc* tdoc) {
+void t_php_generator::generate_php_doc(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_php_docstring_comment(out, tdoc->get_doc());
   }
@@ -2391,7 +2497,7 @@
 /**
  * Emits a PHPDoc comment for a field
  */
-void t_php_generator::generate_php_doc(ofstream& out, t_field* field) {
+void t_php_generator::generate_php_doc(ostream& out, t_field* field) {
   stringstream ss;
 
   // prepend free-style doc if available
@@ -2409,7 +2515,7 @@
 /**
  * Emits a PHPDoc comment for a function
  */
-void t_php_generator::generate_php_doc(ofstream& out, t_function* function) {
+void t_php_generator::generate_php_doc(ostream& out, t_function* function) {
   stringstream ss;
   if (function->has_doc()) {
     ss << function->get_doc() << endl;
@@ -2672,7 +2778,7 @@
     "    inlined:         Generate PHP inlined files\n"
     "    server:          Generate PHP server stubs\n"
     "    oop:             Generate PHP with object oriented subclasses\n"
-    "    psr4:            Generate each PHP class in separate file (allows PSR4 autoloading)\n"
+    "    classmap:        Generate old-style PHP files (use classmap autoloading)\n"
     "    rest:            Generate PHP REST processors\n"
     "    nsglobal=NAME:   Set global namespace\n"
     "    validate:        Generate PHP validator methods\n"
diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc
index 9078da8..e46207a 100644
--- a/compiler/cpp/src/thrift/generate/t_py_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc
@@ -19,7 +19,9 @@
 
 #include <string>
 #include <fstream>
+#include <iomanip>
 #include <iostream>
+#include <limits>
 #include <vector>
 
 #include <stdlib.h>
@@ -32,7 +34,7 @@
 #include "thrift/generate/t_generator.h"
 
 using std::map;
-using std::ofstream;
+using std::ostream;
 using std::ostringstream;
 using std::string;
 using std::stringstream;
@@ -49,10 +51,9 @@
   t_py_generator(t_program* program,
                  const std::map<std::string, std::string>& parsed_options,
                  const std::string& option_string)
-    : t_generator(program) {
+    : t_generator (program) {
     std::map<std::string, std::string>::const_iterator iter;
 
-
     gen_newstyle_ = true;
     gen_utf8strings_ = true;
     gen_dynbase_ = false;
@@ -165,13 +166,13 @@
    */
 
   void generate_py_struct(t_struct* tstruct, bool is_exception);
-  void generate_py_thrift_spec(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_py_struct_definition(std::ofstream& out,
+  void generate_py_thrift_spec(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_py_struct_definition(std::ostream& out,
                                      t_struct* tstruct,
                                      bool is_xception = false);
-  void generate_py_struct_reader(std::ofstream& out, t_struct* tstruct);
-  void generate_py_struct_writer(std::ofstream& out, t_struct* tstruct);
-  void generate_py_struct_required_validator(std::ofstream& out, t_struct* tstruct);
+  void generate_py_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_py_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_py_struct_required_validator(std::ostream& out, t_struct* tstruct);
   void generate_py_function_helpers(t_function* tfunction);
 
   /**
@@ -189,47 +190,47 @@
    * Serialization constructs
    */
 
-  void generate_deserialize_field(std::ofstream& out,
+  void generate_deserialize_field(std::ostream& out,
                                   t_field* tfield,
                                   std::string prefix = "");
 
-  void generate_deserialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_deserialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_deserialize_set_element(std::ofstream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
 
-  void generate_deserialize_map_element(std::ofstream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
 
-  void generate_deserialize_list_element(std::ofstream& out,
+  void generate_deserialize_list_element(std::ostream& out,
                                          t_list* tlist,
                                          std::string prefix = "");
 
-  void generate_serialize_field(std::ofstream& out, t_field* tfield, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
 
-  void generate_serialize_struct(std::ofstream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
 
-  void generate_serialize_container(std::ofstream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
 
-  void generate_serialize_map_element(std::ofstream& out,
+  void generate_serialize_map_element(std::ostream& out,
                                       t_map* tmap,
                                       std::string kiter,
                                       std::string viter);
 
-  void generate_serialize_set_element(std::ofstream& out, t_set* tmap, std::string iter);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
 
-  void generate_serialize_list_element(std::ofstream& out, t_list* tlist, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
 
-  void generate_python_docstring(std::ofstream& out, t_struct* tstruct);
+  void generate_python_docstring(std::ostream& out, t_struct* tstruct);
 
-  void generate_python_docstring(std::ofstream& out, t_function* tfunction);
+  void generate_python_docstring(std::ostream& out, t_function* tfunction);
 
-  void generate_python_docstring(std::ofstream& out,
+  void generate_python_docstring(std::ostream& out,
                                  t_doc* tdoc,
                                  t_struct* tstruct,
                                  const char* subheader);
 
-  void generate_python_docstring(std::ofstream& out, t_doc* tdoc);
+  void generate_python_docstring(std::ostream& out, t_doc* tdoc);
 
   /**
    * Helper rendering functions
@@ -326,12 +327,21 @@
    * File streams
    */
 
-  std::ofstream f_types_;
-  std::ofstream f_consts_;
-  std::ofstream f_service_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_consts_;
+  ofstream_with_content_based_conditional_update f_service_;
 
   std::string package_dir_;
   std::string module_;
+
+protected:
+  virtual std::set<std::string> lang_keywords() const {
+    std::string keywords[] = { "False", "None", "True", "and", "as", "assert", "break", "class",
+          "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from",
+          "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "print",
+          "raise", "return", "try", "while", "with", "yield" };
+    return std::set<std::string>(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) );
+  }
 };
 
 /**
@@ -373,7 +383,7 @@
   f_consts_.open(f_consts_name.c_str());
 
   string f_init_name = package_dir_ + "/__init__.py";
-  ofstream f_init;
+  ofstream_with_content_based_conditional_update f_init;
   f_init.open(f_init_name.c_str());
   f_init << "__all__ = ['ttypes', 'constants'";
   vector<t_service*> services = program_->get_services();
@@ -541,9 +551,9 @@
       break;
     case t_base_type::TYPE_DOUBLE:
       if (value->get_type() == t_const_value::CV_INTEGER) {
-        out << value->get_integer();
+        out << "float(" << value->get_integer() << ")";
       } else {
-        out << value->get_double();
+        out << emit_double_as_string(value->get_double());
       }
       break;
     default:
@@ -556,8 +566,8 @@
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -581,8 +591,8 @@
     }
     out << "{" << endl;
     indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       indent(out) << render_const_value(ktype, v_iter->first) << ": "
           << render_const_value(vtype, v_iter->second) << "," << endl;
@@ -676,7 +686,7 @@
  *       (1, TType.LIST, 'Children', (TType.STRUCT, (Recursive, None), False), None, ),  # 1
  *   )
  */
-void t_py_generator::generate_py_thrift_spec(ofstream& out,
+void t_py_generator::generate_py_thrift_spec(ostream& out,
                                              t_struct* tstruct,
                                              bool /*is_exception*/) {
   const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
@@ -719,7 +729,7 @@
  *
  * @param tstruct The struct definition
  */
-void t_py_generator::generate_py_struct_definition(ofstream& out,
+void t_py_generator::generate_py_struct_definition(ostream& out,
                                                    t_struct* tstruct,
                                                    bool is_exception) {
   const vector<t_field*>& members = tstruct->get_members();
@@ -918,7 +928,7 @@
 /**
  * Generates the read method for a struct
  */
-void t_py_generator::generate_py_struct_reader(ofstream& out, t_struct* tstruct) {
+void t_py_generator::generate_py_struct_reader(ostream& out, t_struct* tstruct) {
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
@@ -946,6 +956,20 @@
   indent_down();
 
   indent(out) << "iprot.readStructBegin()" << endl;
+  
+  if (is_immutable(tstruct)) {
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* tfield = *f_iter;
+      std::ostringstream result;
+      result << tfield->get_name() << " = ";
+      if (tfield->get_value() != NULL) {
+        result << render_field_default_value(tfield);
+      } else {
+        result << "None";
+      }
+      indent(out) << result.str() << endl;
+     }
+  }
 
   // Loop over reading in fields
   indent(out) << "while True:" << endl;
@@ -1009,7 +1033,7 @@
   out << endl;
 }
 
-void t_py_generator::generate_py_struct_writer(ofstream& out, t_struct* tstruct) {
+void t_py_generator::generate_py_struct_writer(ostream& out, t_struct* tstruct) {
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_sorted_members();
   vector<t_field*>::const_iterator f_iter;
@@ -1055,7 +1079,7 @@
   generate_py_struct_required_validator(out, tstruct);
 }
 
-void t_py_generator::generate_py_struct_required_validator(ofstream& out, t_struct* tstruct) {
+void t_py_generator::generate_py_struct_required_validator(ostream& out, t_struct* tstruct) {
   indent(out) << "def validate(self):" << endl;
   indent_up();
 
@@ -1568,7 +1592,7 @@
   vector<t_function*>::iterator f_iter;
 
   string f_remote_name = package_dir_ + "/" + service_name_ + "-remote";
-  ofstream f_remote;
+  ofstream_with_content_based_conditional_update f_remote;
   f_remote.open(f_remote_name.c_str());
 
   f_remote <<
@@ -1600,7 +1624,6 @@
              << (*f_iter)->get_name() << "(";
     t_struct* arg_struct = (*f_iter)->get_arglist();
     const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
     std::vector<t_field*>::size_type num_args = args.size();
     bool first = true;
     for (std::vector<t_field*>::size_type i = 0; i < num_args; ++i) {
@@ -1706,7 +1729,6 @@
 
     t_struct* arg_struct = (*f_iter)->get_arglist();
     const std::vector<t_field*>& args = arg_struct->get_members();
-    vector<t_field*>::const_iterator a_iter;
     std::vector<t_field*>::size_type num_args = args.size();
 
     f_remote << "if cmd == '" << (*f_iter)->get_name() << "':" << endl;
@@ -1937,8 +1959,10 @@
       indent(f_service_) << "def write_results_success_" << tfunction->get_name()
                          << "(self, success, result, seqid, oprot):" << endl;
       indent_up();
-      f_service_ << indent() << "result.success = success" << endl
-                 << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
+      if (!tfunction->get_returntype()->is_void()) {
+        f_service_ << indent() << "result.success = success" << endl;
+      }
+      f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name()
                  << "\", TMessageType.REPLY, seqid)" << endl
                  << indent() << "result.write(oprot)" << endl
                  << indent() << "oprot.writeMessageEnd()" << endl
@@ -2141,7 +2165,7 @@
 /**
  * Deserializes a field of any type.
  */
-void t_py_generator::generate_deserialize_field(ofstream& out,
+void t_py_generator::generate_deserialize_field(ostream& out,
                                                 t_field* tfield,
                                                 string prefix) {
   t_type* type = get_true_type(tfield->get_type());
@@ -2209,7 +2233,7 @@
 /**
  * Generates an unserializer for a struct, calling read()
  */
-void t_py_generator::generate_deserialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_py_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   if (is_immutable(tstruct)) {
     out << indent() << prefix << " = " << type_name(tstruct) << ".read(iprot)" << endl;
   } else {
@@ -2222,7 +2246,7 @@
  * Serialize a container by writing out the header followed by
  * data and then a footer.
  */
-void t_py_generator::generate_deserialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_py_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
   string size = tmp("_size");
   string ktype = tmp("_ktype");
   string vtype = tmp("_vtype");
@@ -2284,7 +2308,7 @@
 /**
  * Generates code to deserialize a map
  */
-void t_py_generator::generate_deserialize_map_element(ofstream& out, t_map* tmap, string prefix) {
+void t_py_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
@@ -2299,7 +2323,7 @@
 /**
  * Write a set element
  */
-void t_py_generator::generate_deserialize_set_element(ofstream& out, t_set* tset, string prefix) {
+void t_py_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
@@ -2311,7 +2335,7 @@
 /**
  * Write a list element
  */
-void t_py_generator::generate_deserialize_list_element(ofstream& out,
+void t_py_generator::generate_deserialize_list_element(ostream& out,
                                                        t_list* tlist,
                                                        string prefix) {
   string elem = tmp("_elem");
@@ -2328,7 +2352,7 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_py_generator::generate_serialize_field(ofstream& out, t_field* tfield, string prefix) {
+void t_py_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
   t_type* type = get_true_type(tfield->get_type());
 
   // Do nothing for void types
@@ -2400,12 +2424,12 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_py_generator::generate_serialize_struct(ofstream& out, t_struct* tstruct, string prefix) {
+void t_py_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
   (void)tstruct;
   indent(out) << prefix << ".write(oprot)" << endl;
 }
 
-void t_py_generator::generate_serialize_container(ofstream& out, t_type* ttype, string prefix) {
+void t_py_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
   if (ttype->is_map()) {
     indent(out) << "oprot.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
                 << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
@@ -2453,7 +2477,7 @@
  * Serializes the members of a map.
  *
  */
-void t_py_generator::generate_serialize_map_element(ofstream& out,
+void t_py_generator::generate_serialize_map_element(ostream& out,
                                                     t_map* tmap,
                                                     string kiter,
                                                     string viter) {
@@ -2467,7 +2491,7 @@
 /**
  * Serializes the members of a set.
  */
-void t_py_generator::generate_serialize_set_element(ofstream& out, t_set* tset, string iter) {
+void t_py_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
   t_field efield(tset->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2475,7 +2499,7 @@
 /**
  * Serializes the members of a list.
  */
-void t_py_generator::generate_serialize_list_element(ofstream& out, t_list* tlist, string iter) {
+void t_py_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
   t_field efield(tlist->get_elem_type(), iter);
   generate_serialize_field(out, &efield, "");
 }
@@ -2483,21 +2507,21 @@
 /**
  * Generates the docstring for a given struct.
  */
-void t_py_generator::generate_python_docstring(ofstream& out, t_struct* tstruct) {
+void t_py_generator::generate_python_docstring(ostream& out, t_struct* tstruct) {
   generate_python_docstring(out, tstruct, tstruct, "Attributes");
 }
 
 /**
  * Generates the docstring for a given function.
  */
-void t_py_generator::generate_python_docstring(ofstream& out, t_function* tfunction) {
+void t_py_generator::generate_python_docstring(ostream& out, t_function* tfunction) {
   generate_python_docstring(out, tfunction, tfunction->get_arglist(), "Parameters");
 }
 
 /**
  * Generates the docstring for a struct or function.
  */
-void t_py_generator::generate_python_docstring(ofstream& out,
+void t_py_generator::generate_python_docstring(ostream& out,
                                                t_doc* tdoc,
                                                t_struct* tstruct,
                                                const char* subheader) {
@@ -2535,7 +2559,7 @@
 /**
  * Generates the docstring for a generic object.
  */
-void t_py_generator::generate_python_docstring(ofstream& out, t_doc* tdoc) {
+void t_py_generator::generate_python_docstring(ostream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
     generate_docstring_comment(out, "\"\"\"\n", "", tdoc->get_doc(), "\"\"\"\n");
   }
diff --git a/compiler/cpp/src/thrift/generate/t_rb_generator.cc b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
index 924f6f6..13ea249 100644
--- a/compiler/cpp/src/thrift/generate/t_rb_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
@@ -113,6 +113,7 @@
   void generate_enum(t_enum* tenum);
   void generate_const(t_const* tconst);
   void generate_struct(t_struct* tstruct);
+  void generate_forward_declaration(t_struct* tstruct);
   void generate_union(t_struct* tunion);
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
@@ -123,6 +124,7 @@
    * Struct generation code
    */
 
+  void generate_rb_struct_declaration(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
   void generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
   void generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct);
   void generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool is_exception);
@@ -455,8 +457,8 @@
     out.indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -478,8 +480,8 @@
     t_type* vtype = ((t_map*)type)->get_val_type();
     out << "{" << endl;
     out.indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       out.indent();
       render_const_value(out, ktype, v_iter->first) << " => ";
@@ -529,6 +531,29 @@
   }
 }
 
+
+/**
+ * Generates the "forward declarations" for ruby structs.
+ * These are simply a declaration of each class with proper inheritance.
+ * The rest of the struct is still generated in generate_struct as has
+ * always been the case. These declarations allow thrift to generate valid
+ * ruby in cases where thrift structs rely on recursive definitions.
+ */
+void t_rb_generator::generate_forward_declaration(t_struct* tstruct) {
+  generate_rb_struct_declaration(f_types_, tstruct, tstruct->is_xception());
+}
+
+void t_rb_generator::generate_rb_struct_declaration(t_rb_ofstream& out, t_struct* tstruct, bool is_exception) {
+  out.indent() << "class " << type_name(tstruct);
+  if (tstruct->is_union()) {
+    out << " < ::Thrift::Union";
+  }
+  if (is_exception) {
+    out << " < ::Thrift::Exception";
+  }
+  out << "; end" << endl << endl;
+}
+
 /**
  * Generates a struct definition for a thrift exception. Basically the same
  * as a struct but extends the Exception class.
diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
index 28c57f8..9843d7a 100644
--- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
@@ -100,7 +100,7 @@
   string gen_dir_;
 
   // File to which generated code is written.
-  std::ofstream f_gen_;
+  ofstream_with_content_based_conditional_update f_gen_;
 
   // Write the common compiler attributes and module includes to the top of the auto-generated file.
   void render_attributes_and_includes();
@@ -127,7 +127,7 @@
   void render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue);
 
   // Write the actual const value - the right side of a const definition.
-  void render_const_value(t_type* ttype, t_const_value* tvalue);
+  void render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned = true);
 
   // Write a const struct (returned from `const_value` method).
   void render_const_struct(t_type* ttype, t_const_value* tvalue);
@@ -350,12 +350,13 @@
   void render_sync_handler_failed_default_exception_branch(t_function *tfunc);
   void render_sync_handler_send_exception_response(t_function *tfunc, const string &err_var);
   void render_service_call_structs(t_service* tservice);
-  void render_result_value_struct(t_function* tfunc);
+  void render_service_call_args_struct(t_function* tfunc);
+  void render_service_call_result_value_struct(t_function* tfunc);
 
   string handler_successful_return_struct(t_function* tfunc);
 
-  // Writes the result of `render_rift_error_struct` wrapped in an `Err(thrift::Error(...))`.
-  void render_rift_error(
+  // Writes the result of `render_thrift_error_struct` wrapped in an `Err(thrift::Error(...))`.
+  void render_thrift_error(
     const string& error_kind,
     const string& error_struct,
     const string& sub_error_kind,
@@ -376,7 +377,7 @@
   //    message: "This is some error message",
   //  }
   // ```
-  void render_rift_error_struct(
+  void render_thrift_error_struct(
     const string& error_struct,
     const string& sub_error_kind,
     const string& error_message
@@ -410,6 +411,9 @@
   // Return a string representing the rust type given a `t_type`.
   string to_rust_type(t_type* ttype, bool ordered_float = true);
 
+  // Return a string representing the `const` rust type given a `t_type`
+  string to_rust_const_type(t_type* ttype, bool ordered_float = true);
+
   // Return a string representing the rift `protocol::TType` given a `t_type`.
   string to_rust_field_type_enum(t_type* ttype);
 
@@ -473,6 +477,9 @@
   // Return the name of the function that users will have to implement to handle incoming service calls.
   string service_call_handler_function_name(t_function* tfunc);
 
+  // Return the name of the struct used to pack the arguments for the thrift service call.
+  string service_call_args_struct_name(t_function* tfunc);
+
   // Return the name of the struct used to pack the return value
   // and user-defined exceptions for the thrift service call.
   string service_call_result_struct_name(t_function* tfunc);
@@ -495,6 +502,9 @@
   // the server half of a Thrift service.
   string rust_sync_processor_impl_name(t_service *tservice);
 
+  // Return the variant name for an enum variant
+  string rust_enum_variant_name(const string& name);
+
   // Properly uppercase names for use in Rust.
   string rust_upper_case(const string& name);
 
@@ -641,8 +651,8 @@
     throw "cannot generate simple rust constant for " + ttype->get_name();
   }
 
-  f_gen_ << "pub const " << rust_upper_case(name) << ": " << to_rust_type(ttype) << " = ";
-  render_const_value(ttype, tvalue);
+  f_gen_ << "pub const " << rust_upper_case(name) << ": " << to_rust_const_type(ttype) << " = ";
+  render_const_value(ttype, tvalue, false);
   f_gen_ << ";" << endl;
   f_gen_ << endl;
 }
@@ -669,15 +679,22 @@
   f_gen_ << endl;
 }
 
-void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue) {
+void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned) {
   if (ttype->is_base_type()) {
     t_base_type* tbase_type = (t_base_type*)ttype;
     switch (tbase_type->get_base()) {
     case t_base_type::TYPE_STRING:
       if (tbase_type->is_binary()) {
-        f_gen_ << "\"" << tvalue->get_string() << "\""<<  ".to_owned().into_bytes()";
+        if (is_owned) {
+          f_gen_ << "\"" << tvalue->get_string() << "\""<<  ".to_owned().into_bytes()";
+        } else {
+          f_gen_ << "b\"" << tvalue->get_string() << "\"";
+        }
       } else {
-        f_gen_ << "\"" << tvalue->get_string() << "\""<<  ".to_owned()";
+        f_gen_ << "\"" << tvalue->get_string() << "\"";
+        if (is_owned) {
+          f_gen_ << ".to_owned()";
+        }
       }
       break;
     case t_base_type::TYPE_BOOL:
@@ -781,8 +798,8 @@
     << to_rust_type(key_type) << ", " << to_rust_type(val_type)
     << "> = BTreeMap::new();"
     << endl;
-  const map<t_const_value*, t_const_value*>& elems = tvalue->get_map();
-  map<t_const_value*, t_const_value*>::const_iterator elem_iter;
+  const map<t_const_value*, t_const_value*, t_const_value::value_compare>& elems = tvalue->get_map();
+  map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator elem_iter;
   for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) {
     t_const_value* key_value = elem_iter->first;
     t_const_value* val_value = elem_iter->second;
@@ -869,7 +886,7 @@
     render_rustdoc((t_doc*) val);
     f_gen_
       << indent()
-      << uppercase(val->get_name())
+      << rust_enum_variant_name(val->get_name())
       << " = "
       << val->get_value()
       << ","
@@ -930,12 +947,12 @@
     f_gen_
       << indent()
       << val->get_value()
-      << " => Ok(" << enum_name << "::" << uppercase(val->get_name()) << "),"
+      << " => Ok(" << enum_name << "::" << rust_enum_variant_name(val->get_name()) << "),"
       << endl;
   }
   f_gen_ << indent() << "_ => {" << endl;
   indent_up();
-  render_rift_error(
+  render_thrift_error(
     "Protocol",
     "ProtocolError",
     "ProtocolErrorKind::InvalidData",
@@ -1316,7 +1333,7 @@
     indent_up();
     // if we haven't found a valid return value *or* a user exception
     // then we're in trouble; return a default error
-    render_rift_error(
+    render_thrift_error(
       "Application",
       "ApplicationError",
       "ApplicationErrorKind::MissingResult",
@@ -1850,7 +1867,7 @@
   // return the value or an error
   f_gen_ << indent() << "if received_field_count == 0 {" << endl;
   indent_up();
-  render_rift_error(
+  render_thrift_error(
     "Protocol",
     "ProtocolError",
     "ProtocolErrorKind::InvalidData",
@@ -1859,7 +1876,7 @@
   indent_down();
   f_gen_ << indent() << "} else if received_field_count > 1 {" << endl;
   indent_up();
-  render_rift_error(
+  render_thrift_error(
     "Protocol",
     "ProtocolError",
     "ProtocolErrorKind::InvalidData",
@@ -2050,9 +2067,9 @@
   // contains the exceptions as well
   for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) {
     t_function* tfunc = (*func_iter);
-    render_struct(rust_struct_name(tfunc->get_arglist()), tfunc->get_arglist(), t_rs_generator::T_ARGS);
+    render_service_call_args_struct(tfunc);
     if (!tfunc->is_oneway()) {
-      render_result_value_struct(tfunc);
+      render_service_call_result_value_struct(tfunc);
     }
   }
 }
@@ -2297,7 +2314,7 @@
   f_gen_
     << indent()
     << "let call_args = "
-    << rust_struct_name(tfunc->get_arglist())
+    << service_call_args_struct_name(tfunc)
     << " { "
     << struct_fields
     << " };"
@@ -2411,7 +2428,12 @@
   return args.str();
 }
 
-void t_rs_generator::render_result_value_struct(t_function* tfunc) {
+void t_rs_generator::render_service_call_args_struct(t_function* tfunc) {
+    string args_struct_name(service_call_args_struct_name(tfunc));
+    render_struct(args_struct_name, tfunc->get_arglist(), t_rs_generator::T_ARGS);
+}
+
+void t_rs_generator::render_service_call_result_value_struct(t_function* tfunc) {
   string result_struct_name = service_call_result_struct_name(tfunc);
   t_struct result(program_, result_struct_name);
 
@@ -2505,7 +2527,7 @@
   indent_up();
   f_gen_ << indent() << service_processor_name << " {" << endl;
   indent_up();
-  f_gen_ << indent() << "handler: handler," << endl;
+  f_gen_ << indent() << "handler," << endl;
   indent_down();
   f_gen_ << indent() << "}" << endl;
   indent_down();
@@ -2556,7 +2578,7 @@
   render_process_match_statements(tservice);
   f_gen_ << indent() << "method => {" << endl;
   indent_up();
-  render_rift_error(
+  render_thrift_error(
     "Application",
     "ApplicationError",
     "ApplicationErrorKind::UnknownMethod",
@@ -2668,7 +2690,7 @@
     << "let "
     << (has_non_void_args(tfunc) ? "args" : "_")
     << " = "
-    << rust_struct_name(tfunc->get_arglist())
+    << service_call_args_struct_name(tfunc)
     << "::read_from_in_protocol(i_prot)?;"
     << endl;
 
@@ -2835,7 +2857,7 @@
 
   f_gen_ << indent() << "let ret_err = {" << endl;
   indent_up();
-  render_rift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "usr_err.description()");
+  render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "usr_err.description()");
   indent_down();
   f_gen_ << indent() << "};" << endl;
   render_sync_handler_send_exception_response(tfunc, "ret_err");
@@ -2858,7 +2880,7 @@
 void t_rs_generator::render_sync_handler_failed_default_exception_branch(t_function *tfunc) {
   f_gen_ << indent() << "let ret_err = {" << endl;
   indent_up();
-  render_rift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "e.description()");
+  render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "e.description()");
   indent_down();
   f_gen_ << indent() << "};" << endl;
   if (tfunc->is_oneway()) {
@@ -2935,7 +2957,7 @@
   generate_docstring_comment(f_gen_, "", "/// ", tdoc->get_doc(), "");
 }
 
-void t_rs_generator::render_rift_error(
+void t_rs_generator::render_thrift_error(
   const string& error_kind,
   const string& error_struct,
   const string& sub_error_kind,
@@ -2945,14 +2967,14 @@
   indent_up();
   f_gen_ << indent() << "thrift::Error::" << error_kind << "(" << endl;
   indent_up();
-  render_rift_error_struct(error_struct, sub_error_kind, error_message);
+  render_thrift_error_struct(error_struct, sub_error_kind, error_message);
   indent_down();
   f_gen_ << indent() << ")" << endl;
   indent_down();
   f_gen_ << indent() << ")" << endl;
 }
 
-void t_rs_generator::render_rift_error_struct(
+void t_rs_generator::render_thrift_error_struct(
   const string& error_struct,
   const string& sub_error_kind,
   const string& error_message
@@ -3013,7 +3035,7 @@
     rust_type =  ttypedef->is_forward_typedef() ? "Box<" + rust_type + ">" : rust_type;
     return rust_type;
   } else if (ttype->is_enum()) {
-    return rust_namespace(ttype) + ttype->get_name();
+    return rust_namespace(ttype) + rust_camel_case(ttype->get_name());
   } else if (ttype->is_struct() || ttype->is_xception()) {
     return rust_namespace(ttype) + rust_camel_case(ttype->get_name());
   } else if (ttype->is_map()) {
@@ -3030,6 +3052,21 @@
   throw "cannot find rust type for " + ttype->get_name();
 }
 
+string t_rs_generator::to_rust_const_type(t_type* ttype, bool ordered_float) {
+  if (ttype->is_base_type()) {
+    t_base_type* tbase_type = ((t_base_type*)ttype);
+    if (tbase_type->get_base() == t_base_type::TYPE_STRING) {
+      if (tbase_type->is_binary()) {
+        return "&[u8]";
+      } else {
+        return "&str";
+      }
+    }
+  }
+
+  return to_rust_type(ttype, ordered_float);
+}
+
 string t_rs_generator::to_rust_field_type_enum(t_type* ttype) {
   ttype = get_true_type(ttype);
   if (ttype->is_base_type()) {
@@ -3212,8 +3249,13 @@
   return "handle_" + rust_snake_case(tfunc->get_name());
 }
 
+string t_rs_generator::service_call_args_struct_name(t_function* tfunc) {
+  // Thrift automatically appends `Args` to the arglist name. No need to do it here.
+  return rust_camel_case(service_name_) + rust_camel_case(tfunc->get_arglist()->get_name());
+}
+
 string t_rs_generator::service_call_result_struct_name(t_function* tfunc) {
-  return rust_camel_case(tfunc->get_name()) + RESULT_STRUCT_SUFFIX;
+  return rust_camel_case(service_name_) + rust_camel_case(tfunc->get_name()) + RESULT_STRUCT_SUFFIX;
 }
 
 string t_rs_generator::rust_sync_client_marker_trait_name(t_service* tservice) {
@@ -3240,6 +3282,23 @@
   return "T" + rust_camel_case(tservice->get_name()) + "ProcessFunctions";
 }
 
+string t_rs_generator::rust_enum_variant_name(const string &name) {
+  bool all_uppercase = true;
+
+  for (size_t i = 0; i < name.size(); i++) {
+    if (isalnum(name[i]) && islower(name[i])) {
+      all_uppercase = false;
+      break;
+    }
+  }
+
+  if (all_uppercase) {
+    return capitalize(camelcase(lowercase(name)));
+  } else {
+    return capitalize(camelcase(name));
+  }
+}
+
 string t_rs_generator::rust_upper_case(const string& name) {
   string str(uppercase(underscore(name)));
   string_replace(str, "__", "_");
diff --git a/compiler/cpp/src/thrift/generate/t_st_generator.cc b/compiler/cpp/src/thrift/generate/t_st_generator.cc
index 69ed776..595a949 100644
--- a/compiler/cpp/src/thrift/generate/t_st_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_st_generator.cc
@@ -93,8 +93,8 @@
    * Struct generation code
    */
 
-  void generate_st_struct(std::ofstream& out, t_struct* tstruct, bool is_exception);
-  void generate_accessors(std::ofstream& out, t_struct* tstruct);
+  void generate_st_struct(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_accessors(std::ostream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
@@ -124,15 +124,15 @@
 
   std::string st_autogen_comment();
 
-  void st_class_def(std::ofstream& out, std::string name);
-  void st_method(std::ofstream& out, std::string cls, std::string name);
-  void st_method(std::ofstream& out, std::string cls, std::string name, std::string category);
-  void st_close_method(std::ofstream& out);
-  void st_class_method(std::ofstream& out, std::string cls, std::string name);
-  void st_class_method(std::ofstream& out, std::string cls, std::string name, std::string category);
-  void st_setter(std::ofstream& out, std::string cls, std::string name, std::string type);
-  void st_getter(std::ofstream& out, std::string cls, std::string name);
-  void st_accessors(std::ofstream& out, std::string cls, std::string name, std::string type);
+  void st_class_def(std::ostream& out, std::string name);
+  void st_method(std::ostream& out, std::string cls, std::string name);
+  void st_method(std::ostream& out, std::string cls, std::string name, std::string category);
+  void st_close_method(std::ostream& out);
+  void st_class_method(std::ostream& out, std::string cls, std::string name);
+  void st_class_method(std::ostream& out, std::string cls, std::string name, std::string category);
+  void st_setter(std::ostream& out, std::string cls, std::string name, std::string type);
+  void st_getter(std::ostream& out, std::string cls, std::string name);
+  void st_accessors(std::ostream& out, std::string cls, std::string name, std::string type);
 
   std::string class_name();
   static bool is_valid_namespace(const std::string& sub_namespace);
@@ -156,7 +156,7 @@
    * File streams
    */
   int temporary_var;
-  std::ofstream f_;
+  ofstream_with_content_based_conditional_update f_;
 };
 
 /**
@@ -250,7 +250,7 @@
   (void)ttypedef;
 }
 
-void t_st_generator::st_class_def(std::ofstream& out, string name) {
+void t_st_generator::st_class_def(std::ostream& out, string name) {
   out << "Object subclass: #" << prefix(name) << endl;
   indent_up();
   out << indent() << "instanceVariableNames: ''" << endl << indent() << "classVariableNames: ''"
@@ -258,19 +258,19 @@
       << generated_category() << "'!" << endl << endl;
 }
 
-void t_st_generator::st_method(std::ofstream& out, string cls, string name) {
+void t_st_generator::st_method(std::ostream& out, string cls, string name) {
   st_method(out, cls, name, "as yet uncategorized");
 }
 
-void t_st_generator::st_class_method(std::ofstream& out, string cls, string name) {
+void t_st_generator::st_class_method(std::ostream& out, string cls, string name) {
   st_method(out, cls + " class", name);
 }
 
-void t_st_generator::st_class_method(std::ofstream& out, string cls, string name, string category) {
+void t_st_generator::st_class_method(std::ostream& out, string cls, string name, string category) {
   st_method(out, cls, name, category);
 }
 
-void t_st_generator::st_method(std::ofstream& out, string cls, string name, string category) {
+void t_st_generator::st_method(std::ostream& out, string cls, string name, string category) {
   char timestr[50];
   time_t rawtime;
   struct tm* tinfo;
@@ -286,12 +286,12 @@
   out << indent();
 }
 
-void t_st_generator::st_close_method(std::ofstream& out) {
+void t_st_generator::st_close_method(std::ostream& out) {
   out << "! !" << endl << endl;
   indent_down();
 }
 
-void t_st_generator::st_setter(std::ofstream& out,
+void t_st_generator::st_setter(std::ostream& out,
                                string cls,
                                string name,
                                string type = "anObject") {
@@ -300,13 +300,13 @@
   st_close_method(out);
 }
 
-void t_st_generator::st_getter(std::ofstream& out, string cls, string name) {
+void t_st_generator::st_getter(std::ostream& out, string cls, string name) {
   st_method(out, cls, name + "");
   out << "^ " << name;
   st_close_method(out);
 }
 
-void t_st_generator::st_accessors(std::ofstream& out,
+void t_st_generator::st_accessors(std::ostream& out,
                                   string cls,
                                   string name,
                                   string type = "anObject") {
@@ -402,8 +402,8 @@
 
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
@@ -428,8 +428,8 @@
     out << "(Dictionary new" << endl;
     indent_up();
     indent_up();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       out << indent() << indent();
       out << "at: " << render_const_value(ktype, v_iter->first);
@@ -490,7 +490,7 @@
 /**
  * Generates a smalltalk class to represent a struct
  */
-void t_st_generator::generate_st_struct(std::ofstream& out,
+void t_st_generator::generate_st_struct(std::ostream& out,
                                         t_struct* tstruct,
                                         bool is_exception = false) {
   const vector<t_field*>& members = tstruct->get_members();
@@ -542,7 +542,7 @@
   return prefix + capitalize(type_name(type));
 }
 
-void t_st_generator::generate_accessors(std::ofstream& out, t_struct* tstruct) {
+void t_st_generator::generate_accessors(std::ostream& out, t_struct* tstruct) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
   string type;
diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
index 87dd2f0..31db04d 100644
--- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
@@ -31,7 +31,6 @@
 
 using std::map;
 using std::ostream;
-using std::ofstream;
 using std::ostringstream;
 using std::set;
 using std::string;
@@ -41,9 +40,9 @@
 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 +55,33 @@
 
     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,42 +109,39 @@
   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);
 
-  void generate_swift_struct(ofstream& out,
+  void generate_swift_struct(ostream& out,
                              t_struct* tstruct,
                              bool is_private);
-  void generate_swift_struct_init(ofstream& out,
+
+  void generate_swift_struct_init(ostream& out,
                                   t_struct* tstruct,
                                   bool all,
                                   bool is_private);
 
-  void generate_swift_struct_implementation(ofstream& out,
+  void generate_swift_struct_implementation(ostream& out,
                                             t_struct* tstruct,
                                             bool is_result,
                                             bool is_private);
-  void generate_swift_struct_hashable_extension(ofstream& out,
+  void generate_swift_struct_hashable_extension(ostream& out,
                                                 t_struct* tstruct,
                                                 bool is_private);
-  void generate_swift_struct_equatable_extension(ofstream& out,
+  void generate_swift_struct_equatable_extension(ostream& out,
                                                  t_struct* tstruct,
                                                  bool is_private);
-  void generate_swift_struct_thrift_extension(ofstream& out,
+  void generate_swift_struct_thrift_extension(ostream& out,
                                               t_struct* tstruct,
                                               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_struct_reader(ostream& out, t_struct* tstruct, bool is_private);
+
+
+  void generate_swift_struct_printable_extension(ostream& out, t_struct* tstruct);
+  void generate_swift_union_reader(ostream& 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);
@@ -140,28 +151,28 @@
    * Service-level generation functions
    */
 
-  void generate_swift_service_protocol(ofstream& out, t_service* tservice);
-  void generate_swift_service_protocol_async(ofstream& out, t_service* tservice);
+  void generate_swift_service_protocol(ostream& out, t_service* tservice);
+  void generate_swift_service_protocol_async(ostream& out, t_service* tservice);
 
-  void generate_swift_service_client(ofstream& out, t_service* tservice);
-  void generate_swift_service_client_async(ofstream& out, t_service* tservice);
+  void generate_swift_service_client(ostream& out, t_service* tservice);
+  void generate_swift_service_client_async(ostream& out, t_service* tservice);
 
-  void generate_swift_service_client_send_function_implementation(ofstream& out,
+  void generate_swift_service_client_send_function_implementation(ostream& out,
                                                                   t_service* tservice,
                                                                   t_function* tfunction,
                                                                   bool needs_protocol);
-  void generate_swift_service_client_send_function_invocation(ofstream& out, t_function* tfunction);
-  void generate_swift_service_client_send_async_function_invocation(ofstream& out,
+  void generate_swift_service_client_send_function_invocation(ostream& out, t_function* tfunction);
+  void generate_swift_service_client_send_async_function_invocation(ostream& out,
                                                                     t_function* tfunction);
-  void generate_swift_service_client_recv_function_implementation(ofstream& out,
+  void generate_swift_service_client_recv_function_implementation(ostream& out,
                                                                   t_service* tservice,
                                                                   t_function* tfunction,
                                                                   bool needs_protocol);
-  void generate_swift_service_client_implementation(ofstream& out, t_service* tservice);
-  void generate_swift_service_client_async_implementation(ofstream& out, t_service* tservice);
+  void generate_swift_service_client_implementation(ostream& out, t_service* tservice);
+  void generate_swift_service_client_async_implementation(ostream& out, t_service* tservice);
 
-  void generate_swift_service_server(ofstream& out, t_service* tservice);
-  void generate_swift_service_server_implementation(ofstream& out, t_service* tservice);
+  void generate_swift_service_server(ostream& out, t_service* tservice);
+  void generate_swift_service_server_implementation(ostream& out, t_service* tservice);
   void generate_swift_service_helpers(t_service* tservice);
 
   /**
@@ -175,13 +186,40 @@
   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(ostream& out, t_function* tfunction);
+  void async_function_docstring(ostream& out, t_function* tfunction);
+  void generate_docstring(ostream& 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(ostream& out,t_struct* tstruct, bool is_private);
+  void generate_old_swift_struct_result_writer(ostream& out, t_struct* tstruct);
+
+  /** Swift 2/Cocoa backwards compatibility*/
+  void generate_old_enum(t_enum* tenum);
+  void generate_old_swift_struct(ostream& out,
+                                 t_struct* tstruct,
+                                 bool is_private);
+  void generate_old_swift_service_client_async_implementation(ostream& 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 +233,15 @@
     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) {
@@ -228,15 +272,22 @@
    * File streams
    */
 
-  ofstream f_decl_;
-  ofstream f_impl_;
+  ofstream_with_content_based_conditional_update f_decl_;
+  ofstream_with_content_based_conditional_update f_impl_;
 
   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 +296,21 @@
  */
 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 = program_name_;
+  if (namespaced_ && !module.empty()) {
+    module_path = module_path + "/" + module;
+    name = 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 +318,8 @@
   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 +345,12 @@
     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 +366,7 @@
   vector<string> includes_list;
   includes_list.push_back("Thrift");
 
-  if (promise_kit_) {
+  if (gen_cocoa_ && promise_kit_) {
     includes_list.push_back("PromiseKit");
   }
 
@@ -337,14 +402,110 @@
   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 +546,31 @@
   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 +611,7 @@
 }
 
 /**
- * Exceptions are structs, but they conform to ErrorType
+ * Exceptions are structs, but they conform to Error
  *
  * @param tstruct The struct definition
  */
@@ -434,6 +620,34 @@
   generate_swift_struct_implementation(f_impl_, txception, false, false);
 }
 
+void t_swift_generator::generate_docstring(ostream& 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.
@@ -442,10 +656,87 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct(ofstream& out,
+void t_swift_generator::generate_swift_struct(ostream& 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(ostream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_private) {
   string visibility = is_private ? "private" : "public";
 
   out << indent() << visibility << " final class " << tstruct->get_name();
@@ -495,12 +786,12 @@
  * @param is_private
  *                Is the initializer public or private
  */
-void t_swift_generator::generate_swift_struct_init(ofstream& out,
+void t_swift_generator::generate_swift_struct_init(ostream& out,
                                                    t_struct* tstruct,
                                                    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 +817,19 @@
   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;
+      }
     }
   }
 
@@ -544,38 +845,39 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_hashable_extension(ofstream& out,
+void t_swift_generator::generate_swift_struct_hashable_extension(ostream& 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 +885,8 @@
   }
 
   block_close(out);
-
   out << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -598,46 +897,55 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_equatable_extension(ofstream& out,
+void t_swift_generator::generate_swift_struct_equatable_extension(ostream& out,
                                                                   t_struct* tstruct,
                                                                   bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
+  string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
 
-  indent(out) << visibility << " func ==(lhs: " << type_name(tstruct) << ", rhs: " << type_name(tstruct) << ") -> Bool";
-
+  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;
 }
 
@@ -651,14 +959,14 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_implementation(ofstream& out,
+void t_swift_generator::generate_swift_struct_implementation(ostream& out,
                                                              t_struct* tstruct,
                                                              bool is_result,
                                                              bool is_private) {
 
   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);
   }
 
@@ -677,7 +985,7 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_thrift_extension(ofstream& out,
+void t_swift_generator::generate_swift_struct_thrift_extension(ostream& out,
                                                                t_struct* tstruct,
                                                                bool is_result,
                                                                bool is_private) {
@@ -687,21 +995,130 @@
   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;
 }
 
+void t_swift_generator::generate_swift_union_reader(ostream& 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) << "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;
+
+  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()) << "):";
+    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) << 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):  try proto.skip(type: unknownType)" << endl;
+
+  block_close(out);
+  indent(out) << "try proto.readFieldEnd()" << endl;
+
+  block_close(out);
+  out << 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) << "throw TProtocolError(error: .unknown, message: \"Missing required value for type: "
+              << tstruct->get_name() << "\")";
+  block_close(out);
+  out << endl;
+
+}
+
 /**
  * Generates a function to read a struct from
  * from a protocol. (TStruct compliance)
@@ -710,100 +1127,196 @@
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_reader(ofstream& out,
+void t_swift_generator::generate_swift_struct_reader(ostream& out,
                                                      t_struct* tstruct,
                                                      bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
+  if (!gen_cocoa_) {
+    /** Swift 3 case */
+    string visibility = is_private ? "fileprivate" : "public";
 
-  indent(out) << visibility << " static func readValueFromProtocol(__proto: TProtocol) throws -> "
-              << tstruct->get_name();
+    indent(out) << visibility << " static func read(from proto: TProtocol) throws -> "
+               << tstruct->get_name();
 
-  block_open(out);
+    block_open(out);
+    indent(out) << "_ = try proto.readStructBegin()" << endl;
 
-  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;
+    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) {
-      if (field_is_optional(*f_iter)) {
-        continue;
-      }
-      indent(out) << "try __proto.validateValue(" << (*f_iter)->get_name() << ", "
-                  << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
+      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;
+    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 << ", ";
+    // 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()) << "):";
+      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 = "            ";
+      }
+
+      out << padding << maybe_escape_identifier((*f_iter)->get_name()) << " = try "
+          << type_name((*f_iter)->get_type(), false, false) << ".read(from: proto)" << endl;
+    }
+
+    indent(out) << "case let (_, unknownType):  try proto.skip(type: unknownType)" << endl;
+    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;
+
+    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 +1328,21 @@
 
 /**
  * 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(ostream& 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 +1350,6 @@
   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 +1376,30 @@
   }
 
   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) {
+void t_swift_generator::generate_old_swift_struct_result_writer(ostream& out, t_struct* tstruct) {
 
-  indent(out) << "private static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";
-
+  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 +1418,8 @@
   }
   // Write the struct map
   indent(out) << "try __proto.writeFieldStop()" << endl << endl;
-
   indent(out) << "try __proto.writeStructEnd()" << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -927,43 +1428,60 @@
  *
  * @param tstruct The struct definition
  */
-void t_swift_generator::generate_swift_struct_printable_extension(ofstream& out, t_struct* tstruct) {
+void t_swift_generator::generate_swift_struct_printable_extension(ostream& out, t_struct* tstruct) {
 
   // 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;
-
   block_close(out);
-
   out << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1076,29 +1594,47 @@
  *
  * @param tservice The service to generate a protocol definition for
  */
-void t_swift_generator::generate_swift_service_protocol(ofstream& out, t_service* tservice) {
+void t_swift_generator::generate_swift_service_protocol(ostream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    string doc = tservice->get_doc();
+    generate_docstring(out, doc);
 
-  indent(out) << "public protocol " << tservice->get_name();
-
-  block_open(out);
-
-  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()) + ", ";
+    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;
+
+    vector<t_function*> functions = tservice->get_functions();
+    vector<t_function*>::iterator f_iter;
+
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      function_docstring(out, *f_iter);
+      indent(out) << function_signature(*f_iter) << endl << endl;
+    }
+
+  } else {
+    indent(out) << "public protocol " << tservice->get_name();
+    block_open(out);
+
+    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;
+    }
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1107,26 +1643,78 @@
  *
  * @param tservice The service to generate a protocol definition for
  */
-void t_swift_generator::generate_swift_service_protocol_async(ofstream& out, t_service* tservice) {
-
+void t_swift_generator::generate_swift_service_protocol_async(ostream& 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;
+    }
+  }
+  block_close(out);
+  out << endl;
+}
+
+/**
+ * Generates a service client interface definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_swift_generator::generate_swift_service_client(ostream& 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) << "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;
+    indent(out) << "__outProtocol = outProtocol" << endl;
+    block_close(out);
     out << endl;
   }
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1135,80 +1723,35 @@
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_swift_generator::generate_swift_service_client(ofstream& out,
-                                                                t_service* tservice) {
+void t_swift_generator::generate_swift_service_client_async(ostream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    indent(out) << "open class " << tservice->get_name()
+                << "AsyncClient<Protocol: TProtocol, Factory: TAsyncTransportFactory>";// : "
 
-  indent(out) << "public class " << tservice->get_name() << "Client /* : " << tservice->get_name() << " */";
+    // Inherit from ParentClient
+    t_service* parent = tservice->get_extends();
 
-  block_open(out);
+    out << " : " << ((parent == NULL) ? "T" :  parent->get_name()) + "AsyncClient<Protocol, Factory>";
+    out <<  " /* , " << tservice->get_name() << " */";
 
-  out << endl;
+    block_open(out);
+    out << endl;
+  } else {
+    indent(out) << "public class " << tservice->get_name() << "AsyncClient /* : " << tservice->get_name() << " */";
+    block_open(out);
+    out << endl;
 
-  indent(out) << "let __inProtocol : TProtocol" << endl << 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) << "let __outProtocol : TProtocol" << endl << endl;
-
-  indent(out) << "public init(inoutProtocol: TProtocol)";
-
-  block_open(out);
-
-  indent(out) << "__inProtocol = inoutProtocol" << endl;
-
-  indent(out) << "__outProtocol = inoutProtocol" << endl;
-
+    indent(out) << "__protocolFactory = protocolFactory" << endl;
+    indent(out) << "__transportFactory = transportFactory" << endl;
+    block_close(out);
+    out << endl;
+  }
   block_close(out);
-
-  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;
-}
-
-/**
- * Generates a service client interface definition.
- *
- * @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)";
-
-  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 +1761,38 @@
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_swift_generator::generate_swift_service_server(ofstream& out,
-                                                                t_service* tservice) {
+void t_swift_generator::generate_swift_service_server(ostream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    indent(out) << "open class " << tservice->get_name() << "Processor /* " << tservice->get_name() << " */";
 
-  indent(out) << "public class " << tservice->get_name() << "Processor : NSObject /* " << tservice->get_name() << " */";
+    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;
 
-  block_open(out);
+    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 << 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() << ")";
   block_open(out);
   indent(out) << "self.service = service" << endl;
   block_close(out);
-
   out << endl;
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1254,7 +1806,7 @@
  *                  Wether the first parameter must be a protocol or if
  *                  the protocol is to be assumed
  */
-void t_swift_generator::generate_swift_service_client_send_function_implementation(ofstream& out,
+void t_swift_generator::generate_swift_service_client_send_function_implementation(ostream& out,
                                                                                    t_service *tservice,
                                                                                    t_function* tfunction,
                                                                                    bool needs_protocol) {
@@ -1268,40 +1820,65 @@
   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;
 
-  indent(out) << "let __args = " << argsname << "(";
-
-  // 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 << ", ";
+    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;
+    out << ")" << endl;
+    indent(out) << "try args.write(to: outProtocol)" << endl;
+    indent(out) << "try outProtocol.writeMessageEnd()" << endl;
+  } else {
+    out << endl;
 
-  indent(out) << "try __outProtocol.writeMessageEnd()" << endl;
+    // Serialize the request
+    indent(out) << "try __outProtocol.writeMessageBeginWithName(\"" << funname << "\", "
+                << "type: " << (tfunction->is_oneway() ? ".ONEWAY" : ".CALL") << ", "
+                << "sequenceID: 0)" << endl;
+
+    out << endl;
+
+    indent(out) << "let __args = " << argsname << "(";
+
+    // 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;
+  }
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1315,73 +1892,122 @@
  *                  Wether the first parameter must be a protocol or if
  *                  the protocol is to be assumed
  */
-void t_swift_generator::generate_swift_service_client_recv_function_implementation(ofstream& out,
+void t_swift_generator::generate_swift_service_client_recv_function_implementation(ostream& out,
                                                                                    t_service* tservice,
                                                                                    t_function* tfunction,
                                                                                    bool needs_protocol) {
 
   // 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";
-  }
-
-  out << ") throws";
-
-  if (!tfunction->get_returntype()->is_void()) {
-    out << " -> " << type_name(tfunction->get_returntype());
-  }
-
-  block_open(out);
-
-  // 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;
-
-  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;
+    // check for an exception
 
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    indent(out) << "if let " << (*x_iter)->get_name() << " = __result." << (*x_iter)->get_name();
+    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;
+
+    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 TApplicationError(error: .missingResult(methodName: \""
+                  << tfunction->get_name() << "\"))" << endl;
+    }
+  } else {
+    if (needs_protocol) {
+      out << "__inProtocol: TProtocol";
+    }
+
+    out << ") throws";
+
+    if (!tfunction->get_returntype()->is_void()) {
+      out << " -> " << type_name(tfunction->get_returntype());
+    }
+
     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();
+    // 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;
+
+    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;
+
+    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;
 }
 
@@ -1391,7 +2017,7 @@
  *
  * @param tfunction The service to generate an implementation for
  */
-void t_swift_generator::generate_swift_service_client_send_function_invocation(ofstream& out,
+void t_swift_generator::generate_swift_service_client_send_function_invocation(ostream& out,
                                                                                t_function* tfunction) {
 
   indent(out) << "try send_" << tfunction->get_name() << "(";
@@ -1417,14 +2043,18 @@
  *
  * @param tfunction The service to generate an implementation for
  */
-void t_swift_generator::generate_swift_service_client_send_async_function_invocation(ofstream& out,
+void t_swift_generator::generate_swift_service_client_send_async_function_invocation(ostream& out,
                                                                                      t_function* tfunction) {
 
   t_struct* arg_struct = tfunction->get_arglist();
   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();
@@ -1438,15 +2068,12 @@
  *
  * @param tservice The service to generate an implementation for
  */
-void t_swift_generator::generate_swift_service_client_implementation(ofstream& out,
+void t_swift_generator::generate_swift_service_client_implementation(ostream& out,
                                                                      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 +2089,17 @@
 
     // 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 +2108,10 @@
         indent(out) << "return try recv_" << (*f_iter)->get_name() << "()" << endl;
       }
     }
-
     block_close(out);
-
     out << endl;
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1496,16 +2120,16 @@
  *
  * @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(ostream& 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 +2145,86 @@
 
     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(ostream& 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 +2232,6 @@
         << endl;
 
     generate_swift_service_client_send_async_function_invocation(out, *f_iter);
-
     out << endl;
 
     indent(out) << "__transport.flushWithCompletion(";
@@ -1563,9 +2265,7 @@
       indent(out) << ", failure: failure)" << endl;
     }
 
-
     block_close(out);
-
     out << endl;
 
     // Promise function
@@ -1580,9 +2280,7 @@
           << 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 +2318,13 @@
       }
 
       indent(out) << "return __promise" << endl;
-
       block_close(out);
-
       out << endl;
 
     }
 
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1643,21 +2337,18 @@
  *
  * @param tservice The service to generate an implementation for
  */
-void t_swift_generator::generate_swift_service_server_implementation(ofstream& out,
+void t_swift_generator::generate_swift_service_server_implementation(ostream& out,
                                                                      t_service* tservice) {
 
   string name = tservice->get_name() + "Processor";
 
   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 +2364,17 @@
         << 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 +2387,7 @@
       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 +2395,10 @@
 
       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 +2406,53 @@
       }
 
       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 ";
+
+          t_program* program = (*x_iter)->get_type()->get_program();
+          if ((*x_iter)->get_type()->get_name() == "Error" && namespaced_ && program != program_) {
+            out << get_real_swift_module(program) << ".";
+          }
+          out << (*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 +2463,16 @@
 
   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 +2481,43 @@
   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 +2530,31 @@
  * @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 +2575,7 @@
     return "Void";
   case t_base_type::TYPE_STRING:
     if (type->is_binary()) {
-      return "TBinary";
+      return gen_cocoa_ ? "TBinary" : "Data";
     } else {
       return "String";
     }
@@ -1860,8 +2601,8 @@
  *
  */
 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 +2633,7 @@
       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) << "(";
@@ -1900,8 +2641,8 @@
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (f_iter = fields.begin(); f_iter != fields.end();) {
       t_field* tfield = *f_iter;
@@ -1934,8 +2675,8 @@
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end();) {
 
@@ -1956,8 +2697,8 @@
 
     t_type* etype = ((t_list*)type)->get_elem_type();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end();) {
 
@@ -1976,8 +2717,8 @@
 
     t_type* etype = ((t_set*)type)->get_elem_type();
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
     for (v_iter = val.begin(); v_iter != val.end();) {
 
@@ -2003,17 +2744,22 @@
  */
 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 +2773,9 @@
  */
 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 +2786,110 @@
 }
 
 /**
+ * Renders a function docstring
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+void t_swift_generator::function_docstring(ostream& 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(ostream& 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 +2898,39 @@
 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 +2959,21 @@
     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 +2988,118 @@
  */
 
 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 +3116,70 @@
   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:
-      return result + "I32";
-    case t_base_type::TYPE_I64:
-      return result + "I64";
-    case t_base_type::TYPE_DOUBLE:
-      return result + "DOUBLE";
+  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_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";
+    } 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 +3188,12 @@
 
 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/compiler/cpp/src/thrift/generate/t_xml_generator.cc b/compiler/cpp/src/thrift/generate/t_xml_generator.cc
index e7e01fd..35fed14 100644
--- a/compiler/cpp/src/thrift/generate/t_xml_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_xml_generator.cc
@@ -101,7 +101,7 @@
   bool should_use_default_ns_;
   bool should_use_namespaces_;
 
-  std::ofstream f_xml_;
+  ofstream_with_content_based_conditional_update f_xml_;
 
   std::set<string> programs_;
   std::stack<string> elements_;
@@ -483,8 +483,8 @@
 
   case t_const_value::CV_MAP: {
     write_element_start("map");
-    std::map<t_const_value*, t_const_value*> map = value->get_map();
-    std::map<t_const_value*, t_const_value*>::iterator mit;
+    std::map<t_const_value*, t_const_value*, t_const_value::value_compare> map = value->get_map();
+    std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::iterator mit;
     for (mit = map.begin(); mit != map.end(); ++mit) {
       write_element_start("entry");
       write_element_start("key");
diff --git a/compiler/cpp/src/thrift/generate/t_xsd_generator.cc b/compiler/cpp/src/thrift/generate/t_xsd_generator.cc
index fa51ba0..e487ffc 100644
--- a/compiler/cpp/src/thrift/generate/t_xsd_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_xsd_generator.cc
@@ -103,8 +103,8 @@
   /**
    * Output xsd/php file
    */
-  std::ofstream f_xsd_;
-  std::ofstream f_php_;
+  ofstream_with_content_based_conditional_update f_xsd_;
+  ofstream_with_content_based_conditional_update f_php_;
 
   /**
    * Output string stream
diff --git a/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 b/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9
diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc
index 8421840..cdc171c 100644
--- a/compiler/cpp/src/thrift/main.cc
+++ b/compiler/cpp/src/thrift/main.cc
@@ -805,8 +805,8 @@
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
 
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       if (v_iter->first->get_type() != t_const_value::CV_STRING) {
         throw "type error: " + name + " struct key must be string";
@@ -826,8 +826,8 @@
   } else if (type->is_map()) {
     t_type* k_type = ((t_map*)type)->get_key_type();
     t_type* v_type = ((t_map*)type)->get_val_type();
-    const map<t_const_value*, t_const_value*>& val = value->get_map();
-    map<t_const_value*, t_const_value*>::const_iterator v_iter;
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       validate_const_rec(name + "<key>", k_type, v_iter->first);
       validate_const_rec(name + "<val>", v_type, v_iter->second);
@@ -1028,6 +1028,7 @@
         g_generator_failure = true;
 #endif
       } else if (generator) {
+        generator->validate_input();
         pverbose("Generating \"%s\"\n", iter->c_str());
         generator->generate_program();
         delete generator;
diff --git a/compiler/cpp/src/thrift/parse/t_const_value.h b/compiler/cpp/src/thrift/parse/t_const_value.h
index fc2f648..6a114cf 100644
--- a/compiler/cpp/src/thrift/parse/t_const_value.h
+++ b/compiler/cpp/src/thrift/parse/t_const_value.h
@@ -38,6 +38,17 @@
  */
 class t_const_value {
 public:
+  /**
+   * Comparator to sort fields in ascending order by key.
+   * Make this a functor instead of a function to help GCC inline it.
+   */
+  struct value_compare {
+  public:
+    bool operator()(t_const_value const* const& left, t_const_value const* const& right) const {
+      return *left < *right;
+    }
+  };
+
   enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER, CV_UNKNOWN };
 
   t_const_value() : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)0), valType_(CV_UNKNOWN) {}
@@ -90,7 +101,7 @@
 
   void add_map(t_const_value* key, t_const_value* val) { mapVal_[key] = val; }
 
-  const std::map<t_const_value*, t_const_value*>& get_map() const { return mapVal_; }
+  const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& get_map() const { return mapVal_; }
 
   void set_list() { valType_ = CV_LIST; }
 
@@ -136,8 +147,55 @@
 
   t_const_value_type get_type() const { if (valType_ == CV_UNKNOWN) { throw std::string("unknown t_const_value"); } return valType_; }
 
+  /**
+   * Comparator to sort map fields in ascending order by key and then value.
+   * This is used for map comparison in lexicographic order.
+   */
+  struct map_entry_compare {
+  private:
+    typedef std::pair<t_const_value*, t_const_value*> ConstPair;
+  public:
+    bool operator()(ConstPair left, ConstPair right) const {
+      if (*(left.first) < *(right.first)) {
+        return true;
+      } else {
+        if (*(right.first) < *(left.first)) {
+          return false;
+        } else {
+          return *(left.second) < *(right.second);
+        }
+      }
+    }
+  };
+
+  bool operator < (const t_const_value& that) const {
+    ::t_const_value::t_const_value_type t1 = get_type();
+    ::t_const_value::t_const_value_type t2 = that.get_type();
+    if (t1 != t2)
+      return t1 < t2;
+    switch (t1) {
+    case ::t_const_value::CV_INTEGER:
+      return intVal_ < that.intVal_;
+    case ::t_const_value::CV_DOUBLE:
+      return doubleVal_ < that.doubleVal_;
+    case ::t_const_value::CV_STRING:
+      return stringVal_ < that.stringVal_;
+    case ::t_const_value::CV_IDENTIFIER:
+      return identifierVal_ < that.identifierVal_;
+    case ::t_const_value::CV_MAP:
+      return std::lexicographical_compare(
+          mapVal_.begin(), mapVal_.end(), that.mapVal_.begin(), that.mapVal_.end(), map_entry_compare());
+    case ::t_const_value::CV_LIST:
+      return std::lexicographical_compare(
+          listVal_.begin(), listVal_.end(), that.listVal_.begin(), that.listVal_.end(), value_compare());
+    case ::t_const_value::CV_UNKNOWN:
+    default:
+      throw "unknown value type";
+    }
+  }
+
 private:
-  std::map<t_const_value*, t_const_value*> mapVal_;
+  std::map<t_const_value*, t_const_value*, value_compare> mapVal_;
   std::vector<t_const_value*> listVal_;
   std::string stringVal_;
   int64_t intVal_;
diff --git a/compiler/cpp/src/thrift/parse/t_scope.h b/compiler/cpp/src/thrift/parse/t_scope.h
index 02aa550..6f160a5 100644
--- a/compiler/cpp/src/thrift/parse/t_scope.h
+++ b/compiler/cpp/src/thrift/parse/t_scope.h
@@ -76,8 +76,8 @@
 
   void resolve_const_value(t_const_value* const_val, t_type* ttype) {
     if (ttype->is_map()) {
-      const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
-      std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
+      const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = const_val->get_map();
+      std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
       for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
         resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type());
         resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type());
@@ -96,8 +96,8 @@
       }
     } else if (ttype->is_struct()) {
       t_struct* tstruct = (t_struct*)ttype;
-      const std::map<t_const_value*, t_const_value*>& map = const_val->get_map();
-      std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
+      const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = const_val->get_map();
+      std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
       for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
         t_field* field = tstruct->get_field_by_name(v_iter->first->get_string());
         if (field == NULL) {
@@ -137,8 +137,8 @@
             throw "Constants cannot be of type VOID";
           }
         } else if (const_type->is_map()) {
-          const std::map<t_const_value*, t_const_value*>& map = constant->get_value()->get_map();
-          std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
+          const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = constant->get_value()->get_map();
+          std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
 
           const_val->set_map();
           for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) {
diff --git a/compiler/cpp/src/thrift/plugin/plugin.cc b/compiler/cpp/src/thrift/plugin/plugin.cc
index 0bac135..7c4c432 100644
--- a/compiler/cpp/src/thrift/plugin/plugin.cc
+++ b/compiler/cpp/src/thrift/plugin/plugin.cc
@@ -25,7 +25,9 @@
 #endif
 
 #include <cassert>
+#include <functional>
 #include <iostream>
+#include <memory>
 
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/for_each.hpp>
@@ -35,7 +37,6 @@
 #include "thrift/protocol/TBinaryProtocol.h"
 #include "thrift/transport/TBufferTransports.h"
 #include "thrift/transport/TFDTransport.h"
-#include "thrift/stdcxx.h"
 #include "thrift/plugin/plugin_types.h"
 
 namespace apache {
@@ -119,11 +120,16 @@
 
   void compileAll() {
     boost::for_each(*source | boost::adaptors::map_keys,
-                    stdcxx::bind(&TypeCache::compile, this, stdcxx::placeholders::_1));
+                    std::bind(&TypeCache::compile, this, std::placeholders::_1));
   }
 
   std::map<int64_t, S> const* source;
 
+  void clear() {
+    source = nullptr ;
+    cache.clear() ;
+  }
+
 protected:
   std::map<int64_t, C*> cache;
 
@@ -141,6 +147,12 @@
 TypeCache< ::t_const, t_const> g_const_cache;
 TypeCache< ::t_service, t_service> g_service_cache;
 
+void clear_global_cache() {
+  g_type_cache.clear();
+  g_const_cache.clear();
+  g_service_cache.clear();
+}
+
 void set_global_cache(const TypeRegistry& from) {
   g_type_cache.source = &from.types;
   g_const_cache.source = &from.constants;
@@ -216,7 +228,7 @@
   assert(to);
   THRIFT_ASSIGN_METADATA();
   boost::for_each(from.constants | boost::adaptors::transformed(convert<t_enum_value>),
-                  stdcxx::bind(&::t_enum::append, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_enum::append, to, std::placeholders::_1));
 }
 THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) {
   assert(to);
@@ -253,16 +265,16 @@
   } else if (from.__isset.list_val) {
     to->set_list();
     boost::for_each(from.list_val | boost::adaptors::transformed(&convert<t_const_value>),
-                    stdcxx::bind(&::t_const_value::add_list, to, stdcxx::placeholders::_1));
+                    std::bind(&::t_const_value::add_list, to, std::placeholders::_1));
   } else
     T_CONST_VALUE_CASE(string);
   else T_CONST_VALUE_CASE(integer);
   else T_CONST_VALUE_CASE(double);
-  else {
-    T_CONST_VALUE_CASE(identifier);
-    if (from.__isset.enum_val)
-      to->set_enum(resolve_type< ::t_enum>(from.enum_val));
+  else if (from.__isset.const_identifier_val) {
+    to->set_identifier(from.const_identifier_val.identifier_val) ;
+    to->set_enum(resolve_type< ::t_enum>(from.const_identifier_val.enum_val)) ;
   }
+
 #undef T_CONST_VALUE_CASE
 }
 THRIFT_CONVERSION(t_field, resolve_type< ::t_type>(from.type), from.name, from.key) {
@@ -280,7 +292,7 @@
   to->set_union(from.is_union);
   to->set_xception(from.is_xception);
   boost::for_each(from.members | boost::adaptors::transformed(convert<t_field>),
-                  stdcxx::bind(&::t_struct::append, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_struct::append, to, std::placeholders::_1));
 }
 THRIFT_CONVERSION(t_const,
                   resolve_type< ::t_type>(from.type),
@@ -307,7 +319,7 @@
   THRIFT_ASSIGN_METADATA();
 
   boost::for_each(from.functions | boost::adaptors::transformed(convert<t_function>),
-                  stdcxx::bind(&::t_service::add_function, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_service::add_function, to, std::placeholders::_1));
 
   if (from.__isset.extends_)
     to->set_extends(resolve_service(from.extends_));
@@ -388,9 +400,9 @@
   to->set_out_path(from.out_path, from.out_path_is_absolute);
 
   boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>),
-                  stdcxx::bind(&::t_program::add_typedef, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_program::add_typedef, to, std::placeholders::_1));
   boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>),
-                  stdcxx::bind(&::t_program::add_enum, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_program::add_enum, to, std::placeholders::_1));
   for (std::vector<int64_t>::const_iterator it = from.objects.begin(); it != from.objects.end();
        it++) {
     ::t_struct* t2 = resolve_type< ::t_struct>(*it);
@@ -401,18 +413,18 @@
     }
   }
   boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const),
-                  stdcxx::bind(&::t_program::add_const, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_program::add_const, to, std::placeholders::_1));
   boost::for_each(from.services | boost::adaptors::transformed(&resolve_service),
-                  stdcxx::bind(&::t_program::add_service, to, stdcxx::placeholders::_1));
+                  std::bind(&::t_program::add_service, to, std::placeholders::_1));
 
   for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
        it++) {
     convert(*it, g_program_cache[it->program_id]);
   }
   std::for_each(from.c_includes.begin(), from.c_includes.end(),
-                stdcxx::bind(&::t_program::add_c_include, to, stdcxx::placeholders::_1));
+                std::bind(&::t_program::add_c_include, to, std::placeholders::_1));
   std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(),
-                stdcxx::bind(&::t_program::add_cpp_include, to, stdcxx::placeholders::_1));
+                std::bind(&::t_program::add_cpp_include, to, std::placeholders::_1));
   for (std::map<std::string, std::string>::const_iterator it = from.namespaces.begin();
        it != from.namespaces.end(); it++) {
     to->set_namespace(it->first, it->second);
@@ -426,8 +438,8 @@
 #ifdef _WIN32
   _setmode(fileno(stdin), _O_BINARY);
 #endif
-  stdcxx::shared_ptr<TFramedTransport> transport(
-      new TFramedTransport(stdcxx::make_shared<TFDTransport>(fileno(stdin))));
+  std::shared_ptr<TFramedTransport> transport(
+      new TFramedTransport(std::make_shared<TFDTransport>(fileno(stdin))));
   TBinaryProtocol proto(transport);
   GeneratorInput input;
   try {
@@ -458,9 +470,7 @@
     return ::t_const_value::CV_INTEGER;
   if (v.__isset.double_val)
     return ::t_const_value::CV_DOUBLE;
-  if (v.__isset.identifier_val)
-    return ::t_const_value::CV_IDENTIFIER;
-  if (v.__isset.enum_val)
+  if (v.__isset.const_identifier_val)
     return ::t_const_value::CV_IDENTIFIER;
   throw ThriftPluginError("Unknown const value type");
 }
diff --git a/compiler/cpp/src/thrift/plugin/plugin.thrift b/compiler/cpp/src/thrift/plugin/plugin.thrift
index 1e51310..6d98f99 100644
--- a/compiler/cpp/src/thrift/plugin/plugin.thrift
+++ b/compiler/cpp/src/thrift/plugin/plugin.thrift
@@ -105,15 +105,20 @@
   T_OPT_IN_REQ_OUT = 2
 }
 
+struct t_const_identifier_value {
+  1: required string identifier_val
+  2: required t_type_id enum_val
+}
+
 union t_const_value {
   1: optional map<t_const_value, t_const_value> map_val
   2: optional list<t_const_value> list_val
   3: optional string string_val
   4: optional i64 integer_val
   5: optional double double_val
-  6: optional string identifier_val
-  7: optional t_type_id enum_val
+  8: optional t_const_identifier_value const_identifier_val
 }
+
 struct t_const {
   1: required string name
   2: required t_type_id type
diff --git a/compiler/cpp/src/thrift/plugin/plugin_output.cc b/compiler/cpp/src/thrift/plugin/plugin_output.cc
index 75725a1..f8223de 100644
--- a/compiler/cpp/src/thrift/plugin/plugin_output.cc
+++ b/compiler/cpp/src/thrift/plugin/plugin_output.cc
@@ -39,12 +39,13 @@
 #include "thrift/plugin/plugin.h"
 #include "thrift/plugin/type_util.h"
 #include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/stdcxx.h"
 #include "thrift/transport/TBufferTransports.h"
 #include "thrift/transport/TFDTransport.h"
 
 #include "thrift/plugin/plugin_types.h"
 
+#include <memory>
+
 namespace plugin_output {
 
 template <typename From>
@@ -55,8 +56,8 @@
 }
 
 using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::stdcxx::make_shared;
-using apache::thrift::stdcxx::shared_ptr;
+using std::make_shared;
+using std::shared_ptr;
 using apache::thrift::transport::TFDTransport;
 using apache::thrift::transport::TFramedTransport;
 
@@ -99,29 +100,62 @@
 
 #define THRIFT_ASSIGN_METADATA() convert(reinterpret_cast<t_type*>(from), to.metadata)
 
+// a generator of sequential unique identifiers for addresses -- so
+// that the TypeCache below can use those IDs instead of
+// addresses. This allows GeneratorInput's various
+// t_{program,type,etc}_id types to be dense consecutively-numbered
+// integers, instead of large random-seeming integers.
+//
+// Furthermore, this allows GeneratorInput to be deterministic (no
+// addresses, so no pseudo-randomness) and that means reproducibility
+// of output.
+const int64_t ONE_MILLION = 1000 * 1000;
+class id_generator {
+public:
+  id_generator() : addr2id_(), next_id_(ONE_MILLION) {}
+
+  void clear() {
+    addr2id_.clear() ;
+    next_id_ = ONE_MILLION ;
+  }
+
+  int64_t gensym(const int64_t addr) {
+    if (!addr) return 0L ;
+    std::map<int64_t, int64_t>::iterator it = addr2id_.find(addr);
+    if (it != addr2id_.end()) return it->second ;
+    int64_t id = next_id_++ ;
+    addr2id_.insert(std::make_pair(addr, id)) ;
+    return id ;
+  }
+
+  std::map<int64_t, int64_t> addr2id_ ;
+  int64_t next_id_ ;
+} ;
+
 // To avoid multiple instances of same type, t_type, t_const and t_service are stored in one place
 // and referenced by ID.
 template <typename T>
 struct TypeCache {
   typedef typename plugin::ToType<T>::type to_type;
+  id_generator idgen ;
   std::map<int64_t, to_type> cache;
 
   template <typename T2>
   int64_t store(T2* t) {
-    intptr_t id = reinterpret_cast<intptr_t>(t);
-    if (id) {
-      typename std::map<int64_t, to_type>::iterator it = cache.find(id);
-      if (it == cache.end()) {
-        // HACK: fake resolve for recursive type
-        cache.insert(std::make_pair(id, to_type()));
-        // overwrite with true value
-        cache[id] = convert(t);
-      }
-    }
-    return static_cast<int64_t>(id);
+    intptr_t addr = reinterpret_cast<intptr_t>(t);
+    if (!addr) return 0L ;
+
+    int64_t id = idgen.gensym(addr) ;
+    if (cache.end() != cache.find(id)) return id ;
+
+    // HACK: fake resolve for recursive type
+    cache.insert(std::make_pair(id, to_type()));
+    // overwrite with true value
+    cache[id] = convert(t);
+    return id ;
   }
 
-  void clear() { cache.clear(); }
+  void clear() { cache.clear() ; idgen.clear(); }
 };
 
 template <typename T>
@@ -137,6 +171,8 @@
 T_STORE(const)
 T_STORE(service)
 #undef T_STORE
+// this id_generator is for gensymm-ing t_program_id
+id_generator program_cache ;
 
 #define THRIFT_ASSIGN_ID_N(t, from_name, to_name)                                                  \
   do {                                                                                             \
@@ -157,7 +193,7 @@
   } while (0)
 
 THRIFT_CONVERSION_N(::t_type, plugin::TypeMetadata) {
-  to.program_id = reinterpret_cast<int64_t>(from->get_program());
+  to.program_id = program_cache.gensym(reinterpret_cast<int64_t>(from->get_program()));
   THRIFT_ASSIGN_N(annotations_, annotations, );
   if (from->has_doc()) {
     to.__set_doc(from->get_doc());
@@ -195,8 +231,13 @@
     THRIFT_ASSIGN_N(get_string(), string_val, );
     break;
   case t_const_value::CV_IDENTIFIER:
-    THRIFT_ASSIGN_ID_N(t_type, enum_, enum_val);
-    THRIFT_ASSIGN_N(get_identifier(), identifier_val, );
+    if (from) {
+      apache::thrift::plugin::t_const_identifier_value cidval ;
+      if (from->enum_)
+	cidval.__set_enum_val(store_type<t_type>(from->enum_));
+      cidval.__set_identifier_val(from->get_identifier());
+      to.__set_const_identifier_val(cidval) ;
+    }
     break;
   case t_const_value::CV_MAP:
     to.__isset.map_val = true;
@@ -341,6 +382,7 @@
   type_cache.clear();
   const_cache.clear();
   service_cache.clear();
+  program_cache.clear() ;
 }
 
 THRIFT_CONVERSION(t_program) {
@@ -360,7 +402,7 @@
   THRIFT_ASSIGN_LIST_ID(t_const, const);
   THRIFT_ASSIGN_LIST_ID(t_service, service);
   THRIFT_ASSIGN_LIST_N(t_program, get_includes(), includes);
-  to.program_id = reinterpret_cast<plugin::t_program_id>(from);
+  to.program_id = program_cache.gensym(reinterpret_cast<plugin::t_program_id>(from));
 }
 
 PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options) {
@@ -410,3 +452,4 @@
   return PLUGIN_NOT_FOUND;
 }
 }
+
diff --git a/compiler/cpp/src/thrift/plugin/type_util.h b/compiler/cpp/src/thrift/plugin/type_util.h
index 508b741..996b5c6 100644
--- a/compiler/cpp/src/thrift/plugin/type_util.h
+++ b/compiler/cpp/src/thrift/plugin/type_util.h
@@ -38,6 +38,7 @@
 
 class TypeRegistry;
 void set_global_cache(const TypeRegistry&);
+void clear_global_cache();
 }
 }
 }
diff --git a/compiler/cpp/src/thrift/thriftl.ll b/compiler/cpp/src/thrift/thriftl.ll
index 30669a4..4f783be 100644
--- a/compiler/cpp/src/thrift/thriftl.ll
+++ b/compiler/cpp/src/thrift/thriftl.ll
@@ -76,11 +76,6 @@
 #include "thrift/thrifty.hh"
 #endif
 
-void thrift_reserved_keyword(char* keyword) {
-  yyerror("Cannot use reserved language keyword: \"%s\"\n", keyword);
-  exit(1);
-}
-
 void integer_overflow(char* text) {
   yyerror("This integer is too big: \"%s\"\n", text);
   exit(1);
@@ -269,111 +264,6 @@
 }
 "&"                  { return tok_reference;            }
 
-
-"BEGIN"              { thrift_reserved_keyword(yytext); }
-"END"                { thrift_reserved_keyword(yytext); }
-"__CLASS__"          { thrift_reserved_keyword(yytext); }
-"__DIR__"            { thrift_reserved_keyword(yytext); }
-"__FILE__"           { thrift_reserved_keyword(yytext); }
-"__FUNCTION__"       { thrift_reserved_keyword(yytext); }
-"__LINE__"           { thrift_reserved_keyword(yytext); }
-"__METHOD__"         { thrift_reserved_keyword(yytext); }
-"__NAMESPACE__"      { thrift_reserved_keyword(yytext); }
-"abstract"           { thrift_reserved_keyword(yytext); }
-"alias"              { thrift_reserved_keyword(yytext); }
-"and"                { thrift_reserved_keyword(yytext); }
-"args"               { thrift_reserved_keyword(yytext); }
-"as"                 { thrift_reserved_keyword(yytext); }
-"assert"             { thrift_reserved_keyword(yytext); }
-"begin"              { thrift_reserved_keyword(yytext); }
-"break"              { thrift_reserved_keyword(yytext); }
-"case"               { thrift_reserved_keyword(yytext); }
-"catch"              { thrift_reserved_keyword(yytext); }
-"class"              { thrift_reserved_keyword(yytext); }
-"clone"              { thrift_reserved_keyword(yytext); }
-"continue"           { thrift_reserved_keyword(yytext); }
-"declare"            { thrift_reserved_keyword(yytext); }
-"def"                { thrift_reserved_keyword(yytext); }
-"default"            { thrift_reserved_keyword(yytext); }
-"del"                { thrift_reserved_keyword(yytext); }
-"delete"             { thrift_reserved_keyword(yytext); }
-"do"                 { thrift_reserved_keyword(yytext); }
-"dynamic"            { thrift_reserved_keyword(yytext); }
-"elif"               { thrift_reserved_keyword(yytext); }
-"else"               { thrift_reserved_keyword(yytext); }
-"elseif"             { thrift_reserved_keyword(yytext); }
-"elsif"              { thrift_reserved_keyword(yytext); }
-"end"                { thrift_reserved_keyword(yytext); }
-"enddeclare"         { thrift_reserved_keyword(yytext); }
-"endfor"             { thrift_reserved_keyword(yytext); }
-"endforeach"         { thrift_reserved_keyword(yytext); }
-"endif"              { thrift_reserved_keyword(yytext); }
-"endswitch"          { thrift_reserved_keyword(yytext); }
-"endwhile"           { thrift_reserved_keyword(yytext); }
-"ensure"             { thrift_reserved_keyword(yytext); }
-"except"             { thrift_reserved_keyword(yytext); }
-"exec"               { thrift_reserved_keyword(yytext); }
-"finally"            { thrift_reserved_keyword(yytext); }
-"float"              { thrift_reserved_keyword(yytext); }
-"for"                { thrift_reserved_keyword(yytext); }
-"foreach"            { thrift_reserved_keyword(yytext); }
-"from"               { thrift_reserved_keyword(yytext); }
-"function"           { thrift_reserved_keyword(yytext); }
-"global"             { thrift_reserved_keyword(yytext); }
-"goto"               { thrift_reserved_keyword(yytext); }
-"if"                 { thrift_reserved_keyword(yytext); }
-"implements"         { thrift_reserved_keyword(yytext); }
-"import"             { thrift_reserved_keyword(yytext); }
-"in"                 { thrift_reserved_keyword(yytext); }
-"inline"             { thrift_reserved_keyword(yytext); }
-"instanceof"         { thrift_reserved_keyword(yytext); }
-"interface"          { thrift_reserved_keyword(yytext); }
-"is"                 { thrift_reserved_keyword(yytext); }
-"lambda"             { thrift_reserved_keyword(yytext); }
-"module"             { thrift_reserved_keyword(yytext); }
-"native"             { thrift_reserved_keyword(yytext); }
-"new"                { thrift_reserved_keyword(yytext); }
-"next"               { thrift_reserved_keyword(yytext); }
-"nil"                { thrift_reserved_keyword(yytext); }
-"not"                { thrift_reserved_keyword(yytext); }
-"or"                 { thrift_reserved_keyword(yytext); }
-"package"            { thrift_reserved_keyword(yytext); }
-"pass"               { thrift_reserved_keyword(yytext); }
-"public"             { thrift_reserved_keyword(yytext); }
-"print"              { thrift_reserved_keyword(yytext); }
-"private"            { thrift_reserved_keyword(yytext); }
-"protected"          { thrift_reserved_keyword(yytext); }
-"raise"              { thrift_reserved_keyword(yytext); }
-"redo"               { thrift_reserved_keyword(yytext); }
-"rescue"             { thrift_reserved_keyword(yytext); }
-"retry"              { thrift_reserved_keyword(yytext); }
-"register"           { thrift_reserved_keyword(yytext); }
-"return"             { thrift_reserved_keyword(yytext); }
-"self"               { thrift_reserved_keyword(yytext); }
-"sizeof"             { thrift_reserved_keyword(yytext); }
-"static"             { thrift_reserved_keyword(yytext); }
-"super"              { thrift_reserved_keyword(yytext); }
-"switch"             { thrift_reserved_keyword(yytext); }
-"synchronized"       { thrift_reserved_keyword(yytext); }
-"then"               { thrift_reserved_keyword(yytext); }
-"this"               { thrift_reserved_keyword(yytext); }
-"throw"              { thrift_reserved_keyword(yytext); }
-"transient"          { thrift_reserved_keyword(yytext); }
-"try"                { thrift_reserved_keyword(yytext); }
-"undef"              { thrift_reserved_keyword(yytext); }
-"unless"             { thrift_reserved_keyword(yytext); }
-"unsigned"           { thrift_reserved_keyword(yytext); }
-"until"              { thrift_reserved_keyword(yytext); }
-"use"                { thrift_reserved_keyword(yytext); }
-"var"                { thrift_reserved_keyword(yytext); }
-"virtual"            { thrift_reserved_keyword(yytext); }
-"volatile"           { thrift_reserved_keyword(yytext); }
-"when"               { thrift_reserved_keyword(yytext); }
-"while"              { thrift_reserved_keyword(yytext); }
-"with"               { thrift_reserved_keyword(yytext); }
-"xor"                { thrift_reserved_keyword(yytext); }
-"yield"              { thrift_reserved_keyword(yytext); }
-
 {intconstant} {
   errno = 0;
   yylval.iconst = strtoll(yytext, NULL, 10);
diff --git a/compiler/cpp/src/thrift/thrifty.yy b/compiler/cpp/src/thrift/thrifty.yy
index e4cae0c..df34adf 100644
--- a/compiler/cpp/src/thrift/thrifty.yy
+++ b/compiler/cpp/src/thrift/thrifty.yy
@@ -35,6 +35,7 @@
 #define __STDC_FORMAT_MACROS
 #endif
 #include <stdio.h>
+#include <string.h>
 #ifndef _MSC_VER
 #include <inttypes.h>
 #else
diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt
index c1fe914..a09f23d 100644
--- a/compiler/cpp/test/CMakeLists.txt
+++ b/compiler/cpp/test/CMakeLists.txt
@@ -75,3 +75,18 @@
                  -DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR}
                  -P ${CMAKE_CURRENT_SOURCE_DIR}/cpp_plugin_test.cmake)
 endif()
+
+file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift")
+foreach(LANG ${thrift_compiler_LANGS})
+    foreach(SAMPLE ${KEYWORD_SAMPLES})
+        get_filename_component(FILENAME ${SAMPLE} NAME_WE)
+        add_test(NAME "${LANG}_${FILENAME}"
+            COMMAND thrift-compiler --gen ${LANG} ${SAMPLE})
+        set_tests_properties("${LANG}_${FILENAME}" PROPERTIES
+            PASS_REGULAR_EXPRESSION "Cannot use reserved language keyword")
+    endforeach()
+endforeach()
+
+
+find_package(PythonInterp REQUIRED)
+add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER})
diff --git a/compiler/cpp/test/Makefile.am b/compiler/cpp/test/Makefile.am
index 5a23202..b7fc91d 100644
--- a/compiler/cpp/test/Makefile.am
+++ b/compiler/cpp/test/Makefile.am
@@ -32,6 +32,8 @@
 
 noinst_PROGRAMS = thrift-gen-mycpp
 
+all-local: thrift-gen-bincat
+
 AM_CPPFLAGS += -I$(top_srcdir)/lib/cpp/src -I$(top_builddir)/lib/cpp/src
 
 plugintest_SOURCES = plugin/conversion_test.cc
@@ -43,9 +45,16 @@
 thrift_gen_mycpp_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la
 
 cpp_plugin_test.sh: thrift-gen-mycpp
-TESTS = $(check_PROGRAMS) cpp_plugin_test.sh
+
+thrift-gen-bincat:
+	cp bincat.sh $@
+	chmod 755 $@
+
+plugin_stability_test.sh: thrift-gen-bincat
+
+TESTS = $(check_PROGRAMS) cpp_plugin_test.sh plugin_stability_test.sh
 
 clean-local:
-	$(RM) -rf gen-cpp gen-mycpp
+	$(RM) -rf gen-cpp gen-mycpp gen-bincat thrift-gen-bincat
 
 endif
diff --git a/compiler/cpp/test/bincat.sh b/compiler/cpp/test/bincat.sh
new file mode 100755
index 0000000..c7f9078
--- /dev/null
+++ b/compiler/cpp/test/bincat.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec /bin/cat
diff --git a/compiler/cpp/test/compiler/Included.thrift b/compiler/cpp/test/compiler/Included.thrift
new file mode 100644
index 0000000..ce84ab6
--- /dev/null
+++ b/compiler/cpp/test/compiler/Included.thrift
@@ -0,0 +1,18 @@
+const string foo = "bar"
+
+struct a_struct {
+  1: bool im_true,
+  2: bool im_false,
+  3: i8 a_bite,
+  4: i16 integer16,
+  5: i32 integer32,
+  6: i64 integer64,
+  7: double double_precision,
+  8: string some_characters,
+  9: string zomg_unicode,
+  10: bool what_who,
+}
+
+service AService {
+  i32 a_procedure(1: i32 arg)
+}
diff --git a/compiler/cpp/test/compiler/Including.thrift b/compiler/cpp/test/compiler/Including.thrift
new file mode 100644
index 0000000..677af7b
--- /dev/null
+++ b/compiler/cpp/test/compiler/Including.thrift
@@ -0,0 +1,7 @@
+include "Included.thrift"
+
+const string s = "string"
+
+struct BStruct {
+  1: Included.a_struct one_of_each
+}
diff --git a/compiler/cpp/test/compiler/Single.thrift b/compiler/cpp/test/compiler/Single.thrift
new file mode 100644
index 0000000..2ec301f
--- /dev/null
+++ b/compiler/cpp/test/compiler/Single.thrift
@@ -0,0 +1 @@
+const string foo = "bar"
diff --git a/compiler/cpp/test/compiler/staleness_check.py b/compiler/cpp/test/compiler/staleness_check.py
new file mode 100755
index 0000000..5b11dff
--- /dev/null
+++ b/compiler/cpp/test/compiler/staleness_check.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python3
+#
+# 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.
+#
+from __future__ import print_function
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import unittest
+
+
+class TestStalenessCheck(unittest.TestCase):
+
+    CURRENT_DIR_PATH = os.path.dirname(os.path.realpath(__file__))
+    THRIFT_EXECUTABLE_PATH = None
+    SINGLE_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Single.thrift")
+    INCLUDING_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Including.thrift")
+    INCLUDED_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Included.thrift")
+
+    def test_staleness_check_of_single_thrift_file_without_changed_output(self):
+        temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH)
+
+        command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-o", temp_dir]
+        command += [TestStalenessCheck.SINGLE_THRIFT_FILE_PATH]
+        subprocess.call(command)
+
+        used_file_path = os.path.join(temp_dir, "gen-cpp", "Single_constants.cpp")
+
+        first_modification_time = os.path.getmtime(os.path.join(used_file_path))
+
+        time.sleep(0.1)
+
+        subprocess.call(command)
+
+        second_modification_time = os.path.getmtime(used_file_path)
+
+        self.assertEqual(second_modification_time, first_modification_time)
+
+        shutil.rmtree(temp_dir, ignore_errors=True)
+
+    def test_staleness_check_of_single_thrift_file_with_changed_output(self):
+        temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH)
+
+        command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-o", temp_dir]
+        command += [TestStalenessCheck.SINGLE_THRIFT_FILE_PATH]
+        subprocess.call(command)
+
+        used_file_path = os.path.join(temp_dir, "gen-cpp", "Single_constants.cpp")
+
+        first_modification_time = os.path.getmtime(os.path.join(used_file_path))
+        used_file = open(used_file_path, "r")
+        first_contents = used_file.read()
+        used_file.close()
+
+        used_file = open(used_file_path, "a")
+        used_file.write("\n/* This is a comment */\n")
+        used_file.close()
+
+        time.sleep(0.1)
+
+        subprocess.call(command)
+
+        second_modification_time = os.path.getmtime(used_file_path)
+        used_file = open(used_file_path, "r")
+        second_contents = used_file.read()
+        used_file.close()
+
+        self.assertGreater(second_modification_time, first_modification_time)
+        self.assertEqual(first_contents, second_contents)
+
+        shutil.rmtree(temp_dir, ignore_errors=True)
+
+    def test_staleness_check_of_included_file(self):
+        temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH)
+
+        temp_included_file_path = os.path.join(temp_dir, "Included.thrift")
+        temp_including_file_path = os.path.join(temp_dir, "Including.thrift")
+
+        shutil.copy2(TestStalenessCheck.INCLUDED_THRIFT_FILE_PATH, temp_included_file_path)
+        shutil.copy2(TestStalenessCheck.INCLUDING_THRIFT_FILE_PATH, temp_including_file_path)
+
+        command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-recurse", "-o", temp_dir]
+        command += [temp_including_file_path]
+
+        subprocess.call(command)
+
+        included_constants_cpp_file_path = os.path.join(temp_dir, "gen-cpp", "Included_constants.cpp")
+        including_constants_cpp_file_path = os.path.join(temp_dir, "gen-cpp", "Including_constants.cpp")
+
+        included_constants_cpp_first_modification_time = os.path.getmtime(included_constants_cpp_file_path)
+        including_constants_cpp_first_modification_time = os.path.getmtime(including_constants_cpp_file_path)
+
+        temp_included_file = open(temp_included_file_path, "a")
+        temp_included_file.write("\nconst i32 an_integer = 42\n")
+        temp_included_file.close()
+
+        time.sleep(0.1)
+
+        subprocess.call(command)
+
+        included_constants_cpp_second_modification_time = os.path.getmtime(included_constants_cpp_file_path)
+        including_constants_cpp_second_modification_time = os.path.getmtime(including_constants_cpp_file_path)
+
+        self.assertGreater(
+            included_constants_cpp_second_modification_time, included_constants_cpp_first_modification_time)
+        self.assertEqual(
+            including_constants_cpp_first_modification_time, including_constants_cpp_second_modification_time)
+
+        shutil.rmtree(temp_dir, ignore_errors=True)
+
+
+def suite():
+    suite = unittest.TestSuite()
+    loader = unittest.TestLoader()
+    suite.addTest(loader.loadTestsFromTestCase(TestStalenessCheck))
+    return suite
+
+
+if __name__ == "__main__":
+    # The path of Thrift compiler  is  passed as an argument to the test script.
+    # Remove it to not confuse the unit testing framework
+    TestStalenessCheck.THRIFT_EXECUTABLE_PATH = sys.argv[-1]
+    del sys.argv[-1]
+    unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2))
diff --git a/compiler/cpp/test/keyword-samples/const1_return.thrift b/compiler/cpp/test/keyword-samples/const1_return.thrift
new file mode 100644
index 0000000..735e4ac
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/const1_return.thrift
@@ -0,0 +1 @@
+const bool return = 0
diff --git a/compiler/cpp/test/keyword-samples/enum1_return.thrift b/compiler/cpp/test/keyword-samples/enum1_return.thrift
new file mode 100644
index 0000000..6d834e1
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/enum1_return.thrift
@@ -0,0 +1,2 @@
+enum return {
+}
diff --git a/compiler/cpp/test/keyword-samples/enum2_return.thrift b/compiler/cpp/test/keyword-samples/enum2_return.thrift
new file mode 100644
index 0000000..a2caa8e
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/enum2_return.thrift
@@ -0,0 +1,3 @@
+enum enum_name {
+  return
+}
diff --git a/compiler/cpp/test/keyword-samples/exception1_return.thrift b/compiler/cpp/test/keyword-samples/exception1_return.thrift
new file mode 100644
index 0000000..eadb338
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/exception1_return.thrift
@@ -0,0 +1 @@
+exception return {}
diff --git a/compiler/cpp/test/keyword-samples/exception2_return.thrift b/compiler/cpp/test/keyword-samples/exception2_return.thrift
new file mode 100644
index 0000000..493c352
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/exception2_return.thrift
@@ -0,0 +1,3 @@
+exception exception_name {
+  1: required i8 return
+}
diff --git a/compiler/cpp/test/keyword-samples/service1_return.thrift b/compiler/cpp/test/keyword-samples/service1_return.thrift
new file mode 100644
index 0000000..5286a36
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/service1_return.thrift
@@ -0,0 +1 @@
+service return {}
diff --git a/compiler/cpp/test/keyword-samples/service2_return.thrift b/compiler/cpp/test/keyword-samples/service2_return.thrift
new file mode 100644
index 0000000..6f7331d
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/service2_return.thrift
@@ -0,0 +1,3 @@
+service service_name {
+  bool function_name(1: i32 return)
+}
diff --git a/compiler/cpp/test/keyword-samples/service3_return.thrift b/compiler/cpp/test/keyword-samples/service3_return.thrift
new file mode 100644
index 0000000..c6dd946
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/service3_return.thrift
@@ -0,0 +1,3 @@
+service service_name {
+  void return()
+}
diff --git a/compiler/cpp/test/keyword-samples/service4_return.thrift b/compiler/cpp/test/keyword-samples/service4_return.thrift
new file mode 100644
index 0000000..d0787df
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/service4_return.thrift
@@ -0,0 +1,5 @@
+exception exception_name {}
+
+service service_name {
+  void function_name() throws ( 1: exception_name return)
+}
diff --git a/compiler/cpp/test/keyword-samples/struct1_return.thrift b/compiler/cpp/test/keyword-samples/struct1_return.thrift
new file mode 100644
index 0000000..c82b8b9
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/struct1_return.thrift
@@ -0,0 +1 @@
+struct return {}
diff --git a/compiler/cpp/test/keyword-samples/struct2_return.thrift b/compiler/cpp/test/keyword-samples/struct2_return.thrift
new file mode 100644
index 0000000..a0700d1
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/struct2_return.thrift
@@ -0,0 +1,3 @@
+struct struct_name {
+  1: required bool return = 1
+}
diff --git a/compiler/cpp/test/keyword-samples/typedef1_return.thrift b/compiler/cpp/test/keyword-samples/typedef1_return.thrift
new file mode 100644
index 0000000..f159bb8
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/typedef1_return.thrift
@@ -0,0 +1 @@
+typedef bool return
diff --git a/compiler/cpp/test/keyword-samples/union1_return.thrift b/compiler/cpp/test/keyword-samples/union1_return.thrift
new file mode 100644
index 0000000..368df13
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/union1_return.thrift
@@ -0,0 +1 @@
+union return {}
diff --git a/compiler/cpp/test/keyword-samples/union2_return.thrift b/compiler/cpp/test/keyword-samples/union2_return.thrift
new file mode 100644
index 0000000..9719d1e
--- /dev/null
+++ b/compiler/cpp/test/keyword-samples/union2_return.thrift
@@ -0,0 +1,3 @@
+union union_name {
+  1: optional bool return=1
+}
diff --git a/compiler/cpp/test/plugin/conversion_test.cc b/compiler/cpp/test/plugin/conversion_test.cc
index 5159ba4..3c8d812 100644
--- a/compiler/cpp/test/plugin/conversion_test.cc
+++ b/compiler/cpp/test/plugin/conversion_test.cc
@@ -234,6 +234,8 @@
 template <typename T>
 T* round_trip(T* t) {
   typename plugin::ToType<T>::type p;
+  plugin::clear_global_cache();
+  plugin_output::clear_global_cache();
   plugin_output::convert(t, p);
   migrate_global_cache();
   return plugin::convert(p);
@@ -275,12 +277,12 @@
     BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size());
     {
       std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut_values;
-      for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut->get_map().begin();
+      for (std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator it = sut->get_map().begin();
            it != sut->get_map().end(); it++) {
         sut_values[it->first->get_type()] = it->second->get_type();
       }
       std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut2_values;
-      for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut2->get_map().begin();
+      for (std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator it = sut2->get_map().begin();
            it != sut2->get_map().end(); it++) {
         sut2_values[it->first->get_type()] = it->second->get_type();
       }
diff --git a/compiler/cpp/test/plugin_stability_test.sh b/compiler/cpp/test/plugin_stability_test.sh
new file mode 100755
index 0000000..eb7c93d
--- /dev/null
+++ b/compiler/cpp/test/plugin_stability_test.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+# this file is intended to be invoked by make.
+#
+# This file runs the compiler twice, using a plugin that just invokes
+# /bin/cat, and compares the output.  If GeneratorInput is
+# nondeterminsitic, you'd expect the output to differ from run-to-run.
+# So this tests that in fact, the output is stable from run-to-run.
+set -e
+mkdir -p gen-bincat
+PATH=.:"$PATH" ../thrift -r -gen bincat ../../../test/Include.thrift > gen-bincat/1.ser
+PATH=.:"$PATH" ../thrift -r -gen bincat ../../../test/Include.thrift > gen-bincat/2.ser
+diff --binary gen-bincat/1.ser gen-bincat/2.ser
diff --git a/compiler/cpp/tests/CMakeLists.txt b/compiler/cpp/tests/CMakeLists.txt
new file mode 100644
index 0000000..e2b100c
--- /dev/null
+++ b/compiler/cpp/tests/CMakeLists.txt
@@ -0,0 +1,153 @@
+#
+# 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.
+#
+cmake_minimum_required(VERSION 2.8.12)
+
+project(thrift_compiler_tests)
+
+set(THRIFT_COMPILER_SOURCE_DIR
+    ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+# don't generate ZERO_CHECK
+set(CMAKE_SUPPRESS_REGENERATION true)
+
+configure_file(${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h)
+if(MSVC)
+    # The winflexbison generator outputs some macros that conflict with the Visual Studio 2010 copy of stdint.h
+    # This might be fixed in later versions of Visual Studio, but an easy solution is to include stdint.h first
+    if(HAVE_STDINT_H)
+        add_definitions(-D__STDC_LIMIT_MACROS)
+        add_definitions(/FI"stdint.h")
+    endif(HAVE_STDINT_H)
+endif()
+
+find_package(FLEX REQUIRED)
+find_package(BISON REQUIRED)
+
+# create directory for thrifty and thriftl
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/)
+
+# Create flex and bison files and build the lib parse static library
+BISON_TARGET(thrifty ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc)
+FLEX_TARGET(thriftl ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc)
+ADD_FLEX_BISON_DEPENDENCY(thriftl thrifty)
+
+set(parse_SOURCES
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh
+)
+
+add_library(parse STATIC ${parse_SOURCES})
+
+# Thrift compiler tests
+set(thrift_compiler_tests
+)
+
+# you can add some files manually there 
+set(thrift_compiler_tests_manual_SOURCES
+    # tests file to avoid main in every test file
+    ${CMAKE_CURRENT_SOURCE_DIR}/tests_main.cc
+)
+
+# set variable for tests sources - will be filled later
+set(thrift_compiler_tests_SOURCES
+)
+
+set(thrift_compiler_SOURCES
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/logging.cc # we use logging instead of main to avoid breaking compillation (2 main v)
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/audit/t_audit.cpp
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/common.cc
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/t_generator.cc
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/t_typedef.cc
+    ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/parse.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h
+)
+
+# This macro adds an option THRIFT_COMPILER_${NAME}
+# that allows enabling or disabling certain languages
+macro(THRIFT_ADD_COMPILER name description initial)
+    string(TOUPPER "THRIFT_COMPILER_${name}" enabler)
+    set(src "${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/t_${name}_generator.cc")
+    option(${enabler} ${description} ${initial})
+    if(${enabler})
+        list(APPEND thrift_compiler_SOURCES ${src})
+        file(GLOB thrift_compiler_tests_SOURCES
+            "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.c*"
+            "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.thrift"
+        )
+    endif()
+endmacro()
+
+# The following compiler with unit tests can be enabled or disabled
+THRIFT_ADD_COMPILER(c_glib  "Enable compiler for C with Glib" OFF)
+THRIFT_ADD_COMPILER(cpp     "Enable compiler for C++" OFF)
+THRIFT_ADD_COMPILER(java    "Enable compiler for Java"   OFF)
+THRIFT_ADD_COMPILER(as3     "Enable compiler for ActionScript 3" OFF)
+THRIFT_ADD_COMPILER(dart    "Enable compiler for Dart" OFF)
+THRIFT_ADD_COMPILER(haxe    "Enable compiler for Haxe" OFF)
+THRIFT_ADD_COMPILER(csharp  "Enable compiler for C#" OFF)
+THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON)
+THRIFT_ADD_COMPILER(py      "Enable compiler for Python 2.0" OFF)
+THRIFT_ADD_COMPILER(rb      "Enable compiler for Ruby" OFF)
+THRIFT_ADD_COMPILER(perl    "Enable compiler for Perl" OFF)
+THRIFT_ADD_COMPILER(php     "Enable compiler for PHP" OFF)
+THRIFT_ADD_COMPILER(erl     "Enable compiler for Erlang" OFF)
+THRIFT_ADD_COMPILER(cocoa   "Enable compiler for Cocoa Objective-C" OFF)
+THRIFT_ADD_COMPILER(swift   "Enable compiler for Cocoa Swift" OFF)
+THRIFT_ADD_COMPILER(st      "Enable compiler for Smalltalk" OFF)
+THRIFT_ADD_COMPILER(ocaml   "Enable compiler for OCaml" OFF)
+THRIFT_ADD_COMPILER(hs      "Enable compiler for Haskell" OFF)
+THRIFT_ADD_COMPILER(xsd     "Enable compiler for XSD" OFF)
+THRIFT_ADD_COMPILER(html    "Enable compiler for HTML Documentation" OFF)
+THRIFT_ADD_COMPILER(js      "Enable compiler for JavaScript" OFF)
+THRIFT_ADD_COMPILER(json    "Enable compiler for JSON" OFF)
+THRIFT_ADD_COMPILER(javame  "Enable compiler for Java ME" OFF)
+THRIFT_ADD_COMPILER(delphi  "Enable compiler for Delphi" OFF)
+THRIFT_ADD_COMPILER(go      "Enable compiler for Go" OFF)
+THRIFT_ADD_COMPILER(d       "Enable compiler for D" OFF)
+THRIFT_ADD_COMPILER(lua     "Enable compiler for Lua" OFF)
+THRIFT_ADD_COMPILER(gv      "Enable compiler for GraphViz" OFF)
+THRIFT_ADD_COMPILER(rs      "Enable compiler for Rust" OFF)
+THRIFT_ADD_COMPILER(xml     "Enable compiler for XML" OFF)
+
+# Thrift is looking for include files in the src directory
+# we also add the current binary directory for generated files
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${THRIFT_COMPILER_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/catch)
+
+add_library(thrift_compiler ${thrift_compiler_SOURCES})
+
+#link parse lib to thrift_compiler lib
+target_link_libraries(thrift_compiler parse)
+
+# add tests executable
+add_executable(thrift_compiler_tests ${thrift_compiler_tests_manual_SOURCES} ${thrift_compiler_tests_SOURCES})
+
+# if generates for Visual Studio set thrift_compiler_tests as default project
+if(MSVC)
+    set_property(TARGET thrift_compiler_tests PROPERTY VS_STARTUP_PROJECT thrift_compiler_tests)
+endif()
+
+set_target_properties(thrift_compiler_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin/)
+set_target_properties(thrift_compiler_tests PROPERTIES OUTPUT_NAME thrift_compiler_tests)
+
+target_link_libraries(thrift_compiler_tests thrift_compiler)
+
+enable_testing()
+add_test(NAME ThriftTests COMMAND thrift_compiler_tests)
\ No newline at end of file
diff --git a/compiler/cpp/tests/README.md b/compiler/cpp/tests/README.md
new file mode 100644
index 0000000..27be491
--- /dev/null
+++ b/compiler/cpp/tests/README.md
@@ -0,0 +1,88 @@
+# Build and run compiler tests using CMake
+
+<!-- TOC -->
+
+- [Build and run compiler tests using CMake](#build-and-run-compiler-tests-using-cmake)
+    - [General information](#general-information)
+    - [How to add your tests](#how-to-add-your-tests)
+    - [Build and run tests on Unix-like systems](#build-and-run-tests-on-unix-like-systems)
+        - [Prerequisites:](#prerequisites)
+        - [Build and run test with CMake](#build-and-run-test-with-cmake)
+    - [Build and run tests on Windows](#build-and-run-tests-on-windows)
+        - [Prerequisites:](#prerequisites-1)
+        - [Generation of VS project with CMake, build and run on Windows](#generation-of-vs-project-with-cmake-build-and-run-on-windows)
+
+<!-- /TOC -->
+
+## General information 
+
+Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netcore** implementation)
+
+At current moment these tests use free Catch library (https://github.com/catchorg/Catch2/tree/Catch1.x) for easy test creation and usage.
+Decision to use it was because of simplicity, easy usage, one header file to use, stable community and growing interest  (https://cpp.libhunt.com/project/googletest-google/vs/catch?rel=cmp-cmp)
+
+Also, maybe, later it will be migrated to Catch2 (https://github.com/philsquared/Catch) - depends on need to support legacy compilers (c++98)
+
+## How to add your tests
+
+- Open **CMakeLists.txt**
+- Set **On** to call of **THRIFT_ADD_COMPILER** for your language
+
+``` cmake 
+THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON)
+```
+
+- Create folder with name specified in list of languages in **CMakeLists.txt**
+- Create tests in folder for your language (with extensions like *.c* - cc, cpp, etc)
+  - Don't forget to add include of catch.hpp in your test file
+  ``` C
+  #include "../catch/catch.hpp"
+  ```
+
+- If you need - add files manually to **thrift_compiler_tests_manual_SOURCES** in **CMakeLists.txt** similar to 
+
+``` cmake
+# you can add some files manually there 
+set(thrift_compiler_tests_manual_SOURCES
+    # tests file to avoid main in every test file
+    ${CMAKE_CURRENT_SOURCE_DIR}/tests_main.cc
+)
+```
+
+- Run **cmake** with arguments for your environment and compiler 
+- Enjoy
+
+## Build and run tests on Unix-like systems
+
+### Prerequisites:
+- Install CMake - <https://cmake.org/download/>
+- Install winflexbison - <https://sourceforge.net/projects/winflexbison/>
+
+### Build and run test with CMake
+
+- Run commands in command line in current directory:
+
+```
+mkdir cmake-vs && cd cmake-vs
+cmake ..
+cmake --build .
+ctest -C Debug -V
+```
+
+## Build and run tests on Windows
+
+### Prerequisites:
+- Install CMake - <https://cmake.org/download/>
+- Install winflexbison - <https://sourceforge.net/projects/winflexbison/>
+- Install VS2017 Community Edition - <https://www.visualstudio.com/vs/whatsnew/> (ensure that you installed workload "Desktop Development with C++" for VS2017)
+
+### Generation of VS project with CMake, build and run on Windows
+- Run commands in command line in current directory (ensure that VS installed):
+
+```
+mkdir cmake-vs
+cd cmake-vs
+cmake ..
+cmake --build .
+ctest -C Debug -V
+```
\ No newline at end of file
diff --git a/compiler/cpp/tests/catch/catch.hpp b/compiler/cpp/tests/catch/catch.hpp
new file mode 100644
index 0000000..33d037e
--- /dev/null
+++ b/compiler/cpp/tests/catch/catch.hpp
@@ -0,0 +1,11508 @@
+/*
+ *  Catch v1.9.4
+ *  Generated: 2017-05-16 13:51:55.506519
+ *  ----------------------------------------------------------
+ *  This file has been merged from multiple headers. Please don't edit it directly
+ *  Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+#ifdef __clang__
+#    pragma clang system_header
+#elif defined __GNUC__
+#    pragma GCC system_header
+#endif
+
+// #included from: internal/catch_suppress_warnings.h
+
+#ifdef __clang__
+#   ifdef __ICC // icpc defines the __clang__ macro
+#       pragma warning(push)
+#       pragma warning(disable: 161 1682)
+#   else // __ICC
+#       pragma clang diagnostic ignored "-Wglobal-constructors"
+#       pragma clang diagnostic ignored "-Wvariadic-macros"
+#       pragma clang diagnostic ignored "-Wc99-extensions"
+#       pragma clang diagnostic ignored "-Wunused-variable"
+#       pragma clang diagnostic push
+#       pragma clang diagnostic ignored "-Wpadded"
+#       pragma clang diagnostic ignored "-Wc++98-compat"
+#       pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#       pragma clang diagnostic ignored "-Wswitch-enum"
+#       pragma clang diagnostic ignored "-Wcovered-switch-default"
+#    endif
+#elif defined __GNUC__
+#    pragma GCC diagnostic ignored "-Wvariadic-macros"
+#    pragma GCC diagnostic ignored "-Wunused-variable"
+#    pragma GCC diagnostic ignored "-Wparentheses"
+
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wpadded"
+#endif
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+#  define CATCH_IMPL
+#endif
+
+#ifdef CATCH_IMPL
+#  ifndef CLARA_CONFIG_MAIN
+#    define CLARA_CONFIG_MAIN_NOT_DEFINED
+#    define CLARA_CONFIG_MAIN
+#  endif
+#endif
+
+// #included from: internal/catch_notimplemented_exception.h
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
+
+// #included from: catch_common.h
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+// #included from: catch_compiler_capabilities.h
+#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
+
+// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
+// The following features are defined:
+//
+// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
+// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
+// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
+// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
+// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
+// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
+// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
+// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
+// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
+// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
+
+// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
+
+// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
+// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
+// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// ****************
+// Note to maintainers: if new toggles are added please document them
+// in configuration.md, too
+// ****************
+
+// In general each macro has a _NO_<feature name> form
+// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
+
+#ifdef __cplusplus
+
+#  if __cplusplus >= 201103L
+#    define CATCH_CPP11_OR_GREATER
+#  endif
+
+#  if __cplusplus >= 201402L
+#    define CATCH_CPP14_OR_GREATER
+#  endif
+
+#endif
+
+#ifdef __clang__
+
+#  if __has_feature(cxx_nullptr)
+#    define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+#  endif
+
+#  if __has_feature(cxx_noexcept)
+#    define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#  endif
+
+#   if defined(CATCH_CPP11_OR_GREATER)
+#       define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
+#       define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
+            _Pragma( "clang diagnostic pop" )
+
+#       define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+#       define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+            _Pragma( "clang diagnostic pop" )
+#   endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// We know some environments not to support full POSIX signals
+#if defined(__CYGWIN__) || defined(__QNX__)
+
+#   if !defined(CATCH_CONFIG_POSIX_SIGNALS)
+#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+#   endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Cygwin
+#ifdef __CYGWIN__
+
+// Required for some versions of Cygwin to declare gettimeofday
+// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
+#   define _BSD_SOURCE
+
+#endif // __CYGWIN__
+
+////////////////////////////////////////////////////////////////////////////////
+// Borland
+#ifdef __BORLANDC__
+
+#endif // __BORLANDC__
+
+////////////////////////////////////////////////////////////////////////////////
+// EDG
+#ifdef __EDG_VERSION__
+
+#endif // __EDG_VERSION__
+
+////////////////////////////////////////////////////////////////////////////////
+// Digital Mars
+#ifdef __DMC__
+
+#endif // __DMC__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+#   if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#       define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+#   endif
+
+// - otherwise more recent versions define __cplusplus >= 201103L
+// and will get picked up below
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
+
+#if (_MSC_VER >= 1600)
+#   define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+#   define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
+#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
+#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
+#endif
+
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Use variadic macros if the compiler supports them
+#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
+    ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
+    ( defined __GNUC__ && __GNUC__ >= 3 ) || \
+    ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
+
+#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+
+#endif
+
+// Use __COUNTER__ if the compiler supports it
+#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
+    ( defined __GNUC__  && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
+    ( defined __clang__ && __clang_major__ >= 3 )
+
+#define CATCH_INTERNAL_CONFIG_COUNTER
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// catch all support for C++11
+#if defined(CATCH_CPP11_OR_GREATER)
+
+#  if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
+#    define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+#  endif
+
+#  ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#    define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#  endif
+
+#  ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#    define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#  endif
+
+#  ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
+#    define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
+#  endif
+
+#  ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
+#    define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
+#  endif
+
+#  ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+#    define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+#  endif
+
+#  if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
+#    define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
+#  endif
+
+#  if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
+#    define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
+#  endif
+#  if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
+#    define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#  endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
+#   define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
+#  endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
+#  define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
+# endif
+
+#endif // __cplusplus >= 201103L
+
+// Now set the actual defines based on the above + anything the user has configured
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_NOEXCEPT
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_GENERATED_METHODS
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_IS_ENUM
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_TUPLE
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
+#   define CATCH_CONFIG_VARIADIC_MACROS
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_LONG_LONG
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_OVERRIDE
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_UNIQUE_PTR
+#endif
+// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
+// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
+// This does not affect compilation
+#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
+#   define CATCH_CONFIG_COUNTER
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
+#   define CATCH_CONFIG_CPP11_SHUFFLE
+#endif
+# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
+#  define CATCH_CONFIG_CPP11_TYPE_TRAITS
+# endif
+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
+#   define CATCH_CONFIG_WINDOWS_SEH
+#endif
+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+#   define CATCH_CONFIG_POSIX_SIGNALS
+#endif
+
+#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
+#   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
+#   define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
+#endif
+#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS)
+#   define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
+#   define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+#endif
+
+// noexcept support:
+#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
+#  define CATCH_NOEXCEPT noexcept
+#  define CATCH_NOEXCEPT_IS(x) noexcept(x)
+#else
+#  define CATCH_NOEXCEPT throw()
+#  define CATCH_NOEXCEPT_IS(x)
+#endif
+
+// nullptr support
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+#   define CATCH_NULL nullptr
+#else
+#   define CATCH_NULL NULL
+#endif
+
+// override support
+#ifdef CATCH_CONFIG_CPP11_OVERRIDE
+#   define CATCH_OVERRIDE override
+#else
+#   define CATCH_OVERRIDE
+#endif
+
+// unique_ptr support
+#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
+#   define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
+#else
+#   define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
+#endif
+
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#ifdef CATCH_CONFIG_COUNTER
+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
+#else
+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+#endif
+
+#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
+#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
+
+#include <sstream>
+#include <algorithm>
+
+namespace Catch {
+
+    struct IConfig;
+
+    struct CaseSensitive { enum Choice {
+        Yes,
+        No
+    }; };
+
+    class NonCopyable {
+#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        NonCopyable( NonCopyable const& )              = delete;
+        NonCopyable( NonCopyable && )                  = delete;
+        NonCopyable& operator = ( NonCopyable const& ) = delete;
+        NonCopyable& operator = ( NonCopyable && )     = delete;
+#else
+        NonCopyable( NonCopyable const& info );
+        NonCopyable& operator = ( NonCopyable const& );
+#endif
+
+    protected:
+        NonCopyable() {}
+        virtual ~NonCopyable();
+    };
+
+    class SafeBool {
+    public:
+        typedef void (SafeBool::*type)() const;
+
+        static type makeSafe( bool value ) {
+            return value ? &SafeBool::trueValue : 0;
+        }
+    private:
+        void trueValue() const {}
+    };
+
+    template<typename ContainerT>
+    inline void deleteAll( ContainerT& container ) {
+        typename ContainerT::const_iterator it = container.begin();
+        typename ContainerT::const_iterator itEnd = container.end();
+        for(; it != itEnd; ++it )
+            delete *it;
+    }
+    template<typename AssociativeContainerT>
+    inline void deleteAllValues( AssociativeContainerT& container ) {
+        typename AssociativeContainerT::const_iterator it = container.begin();
+        typename AssociativeContainerT::const_iterator itEnd = container.end();
+        for(; it != itEnd; ++it )
+            delete it->second;
+    }
+
+    bool startsWith( std::string const& s, std::string const& prefix );
+    bool startsWith( std::string const& s, char prefix );
+    bool endsWith( std::string const& s, std::string const& suffix );
+    bool endsWith( std::string const& s, char suffix );
+    bool contains( std::string const& s, std::string const& infix );
+    void toLowerInPlace( std::string& s );
+    std::string toLower( std::string const& s );
+    std::string trim( std::string const& str );
+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
+
+    struct pluralise {
+        pluralise( std::size_t count, std::string const& label );
+
+        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
+
+        std::size_t m_count;
+        std::string m_label;
+    };
+
+    struct SourceLineInfo {
+
+        SourceLineInfo();
+        SourceLineInfo( char const* _file, std::size_t _line );
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        SourceLineInfo(SourceLineInfo const& other)          = default;
+        SourceLineInfo( SourceLineInfo && )                  = default;
+        SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+        SourceLineInfo& operator = ( SourceLineInfo && )     = default;
+#  endif
+        bool empty() const;
+        bool operator == ( SourceLineInfo const& other ) const;
+        bool operator < ( SourceLineInfo const& other ) const;
+
+        char const* file;
+        std::size_t line;
+    };
+
+    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+
+    // This is just here to avoid compiler warnings with macro constants and boolean literals
+    inline bool isTrue( bool value ){ return value; }
+    inline bool alwaysTrue() { return true; }
+    inline bool alwaysFalse() { return false; }
+
+    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+
+    void seedRng( IConfig const& config );
+    unsigned int rngSeed();
+
+    // Use this in variadic streaming macros to allow
+    //    >> +StreamEndStop
+    // as well as
+    //    >> stuff +StreamEndStop
+    struct StreamEndStop {
+        std::string operator+() {
+            return std::string();
+        }
+    };
+    template<typename T>
+    T const& operator + ( T const& value, StreamEndStop ) {
+        return value;
+    }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+namespace Catch {
+
+    class NotImplementedException : public std::exception
+    {
+    public:
+        NotImplementedException( SourceLineInfo const& lineInfo );
+        NotImplementedException( NotImplementedException const& ) {}
+
+        virtual ~NotImplementedException() CATCH_NOEXCEPT {}
+
+        virtual const char* what() const CATCH_NOEXCEPT;
+
+    private:
+        std::string m_what;
+        SourceLineInfo m_lineInfo;
+    };
+
+} // end namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
+
+// #included from: internal/catch_context.h
+#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
+
+// #included from: catch_interfaces_generators.h
+#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct IGeneratorInfo {
+        virtual ~IGeneratorInfo();
+        virtual bool moveNext() = 0;
+        virtual std::size_t getCurrentIndex() const = 0;
+    };
+
+    struct IGeneratorsForTest {
+        virtual ~IGeneratorsForTest();
+
+        virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
+        virtual bool moveNext() = 0;
+    };
+
+    IGeneratorsForTest* createGeneratorsForTest();
+
+} // end namespace Catch
+
+// #included from: catch_ptr.hpp
+#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    // An intrusive reference counting smart pointer.
+    // T must implement addRef() and release() methods
+    // typically implementing the IShared interface
+    template<typename T>
+    class Ptr {
+    public:
+        Ptr() : m_p( CATCH_NULL ){}
+        Ptr( T* p ) : m_p( p ){
+            if( m_p )
+                m_p->addRef();
+        }
+        Ptr( Ptr const& other ) : m_p( other.m_p ){
+            if( m_p )
+                m_p->addRef();
+        }
+        ~Ptr(){
+            if( m_p )
+                m_p->release();
+        }
+        void reset() {
+            if( m_p )
+                m_p->release();
+            m_p = CATCH_NULL;
+        }
+        Ptr& operator = ( T* p ){
+            Ptr temp( p );
+            swap( temp );
+            return *this;
+        }
+        Ptr& operator = ( Ptr const& other ){
+            Ptr temp( other );
+            swap( temp );
+            return *this;
+        }
+        void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
+        T* get() const{ return m_p; }
+        T& operator*() const { return *m_p; }
+        T* operator->() const { return m_p; }
+        bool operator !() const { return m_p == CATCH_NULL; }
+        operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
+
+    private:
+        T* m_p;
+    };
+
+    struct IShared : NonCopyable {
+        virtual ~IShared();
+        virtual void addRef() const = 0;
+        virtual void release() const = 0;
+    };
+
+    template<typename T = IShared>
+    struct SharedImpl : T {
+
+        SharedImpl() : m_rc( 0 ){}
+
+        virtual void addRef() const {
+            ++m_rc;
+        }
+        virtual void release() const {
+            if( --m_rc == 0 )
+                delete this;
+        }
+
+        mutable unsigned int m_rc;
+    };
+
+} // end namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+namespace Catch {
+
+    class TestCase;
+    class Stream;
+    struct IResultCapture;
+    struct IRunner;
+    struct IGeneratorsForTest;
+    struct IConfig;
+
+    struct IContext
+    {
+        virtual ~IContext();
+
+        virtual IResultCapture* getResultCapture() = 0;
+        virtual IRunner* getRunner() = 0;
+        virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
+        virtual bool advanceGeneratorsForCurrentTest() = 0;
+        virtual Ptr<IConfig const> getConfig() const = 0;
+    };
+
+    struct IMutableContext : IContext
+    {
+        virtual ~IMutableContext();
+        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+        virtual void setRunner( IRunner* runner ) = 0;
+        virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
+    };
+
+    IContext& getCurrentContext();
+    IMutableContext& getCurrentMutableContext();
+    void cleanUpContext();
+    Stream createStream( std::string const& streamName );
+
+}
+
+// #included from: internal/catch_test_registry.hpp
+#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
+
+// #included from: catch_interfaces_testcase.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
+
+#include <vector>
+
+namespace Catch {
+
+    class TestSpec;
+
+    struct ITestCase : IShared {
+        virtual void invoke () const = 0;
+    protected:
+        virtual ~ITestCase();
+    };
+
+    class TestCase;
+    struct IConfig;
+
+    struct ITestCaseRegistry {
+        virtual ~ITestCaseRegistry();
+        virtual std::vector<TestCase> const& getAllTests() const = 0;
+        virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
+    };
+
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
+
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+public:
+    MethodTestCase( void (C::*method)() ) : m_method( method ) {}
+
+    virtual void invoke() const {
+        C obj;
+        (obj.*m_method)();
+    }
+
+private:
+    virtual ~MethodTestCase() {}
+
+    void (C::*m_method)();
+};
+
+typedef void(*TestFunction)();
+
+struct NameAndDesc {
+    NameAndDesc( const char* _name = "", const char* _description= "" )
+    : name( _name ), description( _description )
+    {}
+
+    const char* name;
+    const char* description;
+};
+
+void registerTestCase
+    (   ITestCase* testCase,
+        char const* className,
+        NameAndDesc const& nameAndDesc,
+        SourceLineInfo const& lineInfo );
+
+struct AutoReg {
+
+    AutoReg
+        (   TestFunction function,
+            SourceLineInfo const& lineInfo,
+            NameAndDesc const& nameAndDesc );
+
+    template<typename C>
+    AutoReg
+        (   void (C::*method)(),
+            char const* className,
+            NameAndDesc const& nameAndDesc,
+            SourceLineInfo const& lineInfo ) {
+
+        registerTestCase
+            (   new MethodTestCase<C>( method ),
+                className,
+                nameAndDesc,
+                lineInfo );
+    }
+
+    ~AutoReg();
+
+private:
+    AutoReg( AutoReg const& );
+    void operator= ( AutoReg const& );
+};
+
+void registerTestCaseFunction
+    (   TestFunction function,
+        SourceLineInfo const& lineInfo,
+        NameAndDesc const& nameAndDesc );
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
+        static void TestName(); \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
+        static void TestName()
+    #define INTERNAL_CATCH_TESTCASE( ... ) \
+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ \
+            struct TestName : ClassName{ \
+                void test(); \
+            }; \
+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
+        } \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
+        void TestName::test()
+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
+        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+
+#else
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
+        static void TestName(); \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
+        static void TestName()
+    #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        namespace{ \
+            struct TestCaseName : ClassName{ \
+                void test(); \
+            }; \
+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
+        } \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
+        void TestCaseName::test()
+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
+        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
+        CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
+        Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \
+        CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+
+#endif
+
+// #included from: internal/catch_capture.hpp
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+// #included from: catch_result_builder.h
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
+
+// #included from: catch_result_type.h
+#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
+
+namespace Catch {
+
+    // ResultWas::OfType enum
+    struct ResultWas { enum OfType {
+        Unknown = -1,
+        Ok = 0,
+        Info = 1,
+        Warning = 2,
+
+        FailureBit = 0x10,
+
+        ExpressionFailed = FailureBit | 1,
+        ExplicitFailure = FailureBit | 2,
+
+        Exception = 0x100 | FailureBit,
+
+        ThrewException = Exception | 1,
+        DidntThrowException = Exception | 2,
+
+        FatalErrorCondition = 0x200 | FailureBit
+
+    }; };
+
+    inline bool isOk( ResultWas::OfType resultType ) {
+        return ( resultType & ResultWas::FailureBit ) == 0;
+    }
+    inline bool isJustInfo( int flags ) {
+        return flags == ResultWas::Info;
+    }
+
+    // ResultDisposition::Flags enum
+    struct ResultDisposition { enum Flags {
+        Normal = 0x01,
+
+        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
+        FalseTest = 0x04,           // Prefix expression with !
+        SuppressFail = 0x08         // Failures are reported but do not fail the test
+    }; };
+
+    inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
+        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
+    }
+
+    inline bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
+    inline bool isFalseTest( int flags )                { return ( flags & ResultDisposition::FalseTest ) != 0; }
+    inline bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.h
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+
+    struct DecomposedExpression
+    {
+        virtual ~DecomposedExpression() {}
+        virtual bool isBinaryExpression() const {
+            return false;
+        }
+        virtual void reconstructExpression( std::string& dest ) const = 0;
+
+        // Only simple binary comparisons can be decomposed.
+        // If more complex check is required then wrap sub-expressions in parentheses.
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
+        template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
+
+	private:
+		DecomposedExpression& operator = (DecomposedExpression const&);
+    };
+
+    struct AssertionInfo
+    {
+        AssertionInfo() {}
+        AssertionInfo(  std::string const& _macroName,
+                        SourceLineInfo const& _lineInfo,
+                        std::string const& _capturedExpression,
+                        ResultDisposition::Flags _resultDisposition );
+
+        std::string macroName;
+        SourceLineInfo lineInfo;
+        std::string capturedExpression;
+        ResultDisposition::Flags resultDisposition;
+    };
+
+    struct AssertionResultData
+    {
+        AssertionResultData() : decomposedExpression( CATCH_NULL )
+                              , resultType( ResultWas::Unknown )
+                              , negated( false )
+                              , parenthesized( false ) {}
+
+        void negate( bool parenthesize ) {
+            negated = !negated;
+            parenthesized = parenthesize;
+            if( resultType == ResultWas::Ok )
+                resultType = ResultWas::ExpressionFailed;
+            else if( resultType == ResultWas::ExpressionFailed )
+                resultType = ResultWas::Ok;
+        }
+
+        std::string const& reconstructExpression() const {
+            if( decomposedExpression != CATCH_NULL ) {
+                decomposedExpression->reconstructExpression( reconstructedExpression );
+                if( parenthesized ) {
+                    reconstructedExpression.insert( 0, 1, '(' );
+                    reconstructedExpression.append( 1, ')' );
+                }
+                if( negated ) {
+                    reconstructedExpression.insert( 0, 1, '!' );
+                }
+                decomposedExpression = CATCH_NULL;
+            }
+            return reconstructedExpression;
+        }
+
+        mutable DecomposedExpression const* decomposedExpression;
+        mutable std::string reconstructedExpression;
+        std::string message;
+        ResultWas::OfType resultType;
+        bool negated;
+        bool parenthesized;
+    };
+
+    class AssertionResult {
+    public:
+        AssertionResult();
+        AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
+        ~AssertionResult();
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+         AssertionResult( AssertionResult const& )              = default;
+         AssertionResult( AssertionResult && )                  = default;
+         AssertionResult& operator = ( AssertionResult const& ) = default;
+         AssertionResult& operator = ( AssertionResult && )     = default;
+#  endif
+
+        bool isOk() const;
+        bool succeeded() const;
+        ResultWas::OfType getResultType() const;
+        bool hasExpression() const;
+        bool hasMessage() const;
+        std::string getExpression() const;
+        std::string getExpressionInMacro() const;
+        bool hasExpandedExpression() const;
+        std::string getExpandedExpression() const;
+        std::string getMessage() const;
+        SourceLineInfo getSourceInfo() const;
+        std::string getTestMacroName() const;
+        void discardDecomposedExpression() const;
+        void expandDecomposedExpression() const;
+
+    protected:
+        AssertionInfo m_info;
+        AssertionResultData m_resultData;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_matchers.hpp
+#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+    namespace Impl {
+
+        template<typename ArgT> struct MatchAllOf;
+        template<typename ArgT> struct MatchAnyOf;
+        template<typename ArgT> struct MatchNotOf;
+
+        class MatcherUntypedBase {
+        public:
+            std::string toString() const {
+                if( m_cachedToString.empty() )
+                    m_cachedToString = describe();
+                return m_cachedToString;
+            }
+
+        protected:
+            virtual ~MatcherUntypedBase();
+            virtual std::string describe() const = 0;
+            mutable std::string m_cachedToString;
+        private:
+            MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
+        };
+
+        template<typename ObjectT>
+        struct MatcherMethod {
+            virtual bool match( ObjectT const& arg ) const = 0;
+        };
+        template<typename PtrT>
+        struct MatcherMethod<PtrT*> {
+            virtual bool match( PtrT* arg ) const = 0;
+        };
+
+        template<typename ObjectT, typename ComparatorT = ObjectT>
+        struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
+
+            MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
+            MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
+            MatchNotOf<ComparatorT> operator ! () const;
+        };
+
+        template<typename ArgT>
+        struct MatchAllOf : MatcherBase<ArgT> {
+            virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if (!m_matchers[i]->match(arg))
+                        return false;
+                }
+                return true;
+            }
+            virtual std::string describe() const CATCH_OVERRIDE {
+                std::string description;
+                description.reserve( 4 + m_matchers.size()*32 );
+                description += "( ";
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if( i != 0 )
+                        description += " and ";
+                    description += m_matchers[i]->toString();
+                }
+                description += " )";
+                return description;
+            }
+
+            MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
+                m_matchers.push_back( &other );
+                return *this;
+            }
+
+            std::vector<MatcherBase<ArgT> const*> m_matchers;
+        };
+        template<typename ArgT>
+        struct MatchAnyOf : MatcherBase<ArgT> {
+
+            virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if (m_matchers[i]->match(arg))
+                        return true;
+                }
+                return false;
+            }
+            virtual std::string describe() const CATCH_OVERRIDE {
+                std::string description;
+                description.reserve( 4 + m_matchers.size()*32 );
+                description += "( ";
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if( i != 0 )
+                        description += " or ";
+                    description += m_matchers[i]->toString();
+                }
+                description += " )";
+                return description;
+            }
+
+            MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
+                m_matchers.push_back( &other );
+                return *this;
+            }
+
+            std::vector<MatcherBase<ArgT> const*> m_matchers;
+        };
+
+        template<typename ArgT>
+        struct MatchNotOf : MatcherBase<ArgT> {
+
+            MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
+
+            virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+                return !m_underlyingMatcher.match( arg );
+            }
+
+            virtual std::string describe() const CATCH_OVERRIDE {
+                return "not " + m_underlyingMatcher.toString();
+            }
+            MatcherBase<ArgT> const& m_underlyingMatcher;
+        };
+
+        template<typename ObjectT, typename ComparatorT>
+        MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
+            return MatchAllOf<ComparatorT>() && *this && other;
+        }
+        template<typename ObjectT, typename ComparatorT>
+        MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
+            return MatchAnyOf<ComparatorT>() || *this || other;
+        }
+        template<typename ObjectT, typename ComparatorT>
+        MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
+            return MatchNotOf<ComparatorT>( *this );
+        }
+
+    } // namespace Impl
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+    // - deprecated: prefer ||, && and !
+    template<typename T>
+    inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
+        return Impl::MatchNotOf<T>( underlyingMatcher );
+    }
+    template<typename T>
+    inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+        return Impl::MatchAllOf<T>() && m1 && m2;
+    }
+    template<typename T>
+    inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+        return Impl::MatchAllOf<T>() && m1 && m2 && m3;
+    }
+    template<typename T>
+    inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+        return Impl::MatchAnyOf<T>() || m1 || m2;
+    }
+    template<typename T>
+    inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+        return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
+    }
+
+} // namespace Matchers
+
+using namespace Matchers;
+using Matchers::Impl::MatcherBase;
+
+} // namespace Catch
+
+namespace Catch {
+
+    struct TestFailureException{};
+
+    template<typename T> class ExpressionLhs;
+
+    struct CopyableStream {
+        CopyableStream() {}
+        CopyableStream( CopyableStream const& other ) {
+            oss << other.oss.str();
+        }
+        CopyableStream& operator=( CopyableStream const& other ) {
+            oss.str(std::string());
+            oss << other.oss.str();
+            return *this;
+        }
+        std::ostringstream oss;
+    };
+
+    class ResultBuilder : public DecomposedExpression {
+    public:
+        ResultBuilder(  char const* macroName,
+                        SourceLineInfo const& lineInfo,
+                        char const* capturedExpression,
+                        ResultDisposition::Flags resultDisposition,
+                        char const* secondArg = "" );
+        ~ResultBuilder();
+
+        template<typename T>
+        ExpressionLhs<T const&> operator <= ( T const& operand );
+        ExpressionLhs<bool> operator <= ( bool value );
+
+        template<typename T>
+        ResultBuilder& operator << ( T const& value ) {
+            m_stream.oss << value;
+            return *this;
+        }
+
+        ResultBuilder& setResultType( ResultWas::OfType result );
+        ResultBuilder& setResultType( bool result );
+
+        void endExpression( DecomposedExpression const& expr );
+
+        virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
+
+        AssertionResult build() const;
+        AssertionResult build( DecomposedExpression const& expr ) const;
+
+        void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
+        void captureResult( ResultWas::OfType resultType );
+        void captureExpression();
+        void captureExpectedException( std::string const& expectedMessage );
+        void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
+        void handleResult( AssertionResult const& result );
+        void react();
+        bool shouldDebugBreak() const;
+        bool allowThrows() const;
+
+        template<typename ArgT, typename MatcherT>
+        void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
+
+        void setExceptionGuard();
+        void unsetExceptionGuard();
+
+    private:
+        AssertionInfo m_assertionInfo;
+        AssertionResultData m_data;
+        CopyableStream m_stream;
+
+        bool m_shouldDebugBreak;
+        bool m_shouldThrow;
+        bool m_guardException;
+    };
+
+} // namespace Catch
+
+// Include after due to circular dependency:
+// #included from: catch_expression_lhs.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
+
+// #included from: catch_evaluate.hpp
+#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
+#endif
+
+#include <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+    enum Operator {
+        IsEqualTo,
+        IsNotEqualTo,
+        IsLessThan,
+        IsGreaterThan,
+        IsLessThanOrEqualTo,
+        IsGreaterThanOrEqualTo
+    };
+
+    template<Operator Op> struct OperatorTraits             { static const char* getName(){ return "*error*"; } };
+    template<> struct OperatorTraits<IsEqualTo>             { static const char* getName(){ return "=="; } };
+    template<> struct OperatorTraits<IsNotEqualTo>          { static const char* getName(){ return "!="; } };
+    template<> struct OperatorTraits<IsLessThan>            { static const char* getName(){ return "<"; } };
+    template<> struct OperatorTraits<IsGreaterThan>         { static const char* getName(){ return ">"; } };
+    template<> struct OperatorTraits<IsLessThanOrEqualTo>   { static const char* getName(){ return "<="; } };
+    template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+    template<typename T>
+    inline T& opCast(T const& t) { return const_cast<T&>(t); }
+
+// nullptr_t support based on pull request #154 from Konstantin Baumann
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+    inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+    // So the compare overloads can be operator agnostic we convey the operator as a template
+    // enum, which is used to specialise an Evaluator for doing the comparison.
+    template<typename T1, typename T2, Operator Op>
+    class Evaluator{};
+
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs) {
+            return bool( opCast( lhs ) ==  opCast( rhs ) );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsNotEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return bool( opCast( lhs ) != opCast( rhs ) );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsLessThan> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return bool( opCast( lhs ) < opCast( rhs ) );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsGreaterThan> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return bool( opCast( lhs ) > opCast( rhs ) );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return bool( opCast( lhs ) >= opCast( rhs ) );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return bool( opCast( lhs ) <= opCast( rhs ) );
+        }
+    };
+
+    template<Operator Op, typename T1, typename T2>
+    bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+        return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+    }
+
+    // This level of indirection allows us to specialise for integer types
+    // to avoid signed/ unsigned warnings
+
+    // "base" overload
+    template<Operator Op, typename T1, typename T2>
+    bool compare( T1 const& lhs, T2 const& rhs ) {
+        return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+    }
+
+    // unsigned X to int
+    template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+
+    // unsigned X to long
+    template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+
+    // int to unsigned X
+    template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+
+    // long to unsigned X
+    template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+
+    // pointer to long (when comparing against NULL)
+    template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+    }
+
+    // pointer to int (when comparing against NULL)
+    template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+    }
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+    // long long to unsigned X
+    template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+
+    // unsigned long long to X
+    template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
+        return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
+        return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
+        return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
+        return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+    }
+
+    // pointer to long long (when comparing against NULL)
+    template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+    }
+#endif // CATCH_CONFIG_CPP11_LONG_LONG
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+    // pointer to nullptr_t (when comparing against nullptr)
+    template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
+    }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+} // end of namespace Internal
+} // end of namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// #included from: catch_tostring.h
+#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+    [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_TUPLE
+#include <tuple>
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_IS_ENUM
+#include <type_traits>
+#endif
+
+namespace Catch {
+
+// Why we're here.
+template<typename T>
+std::string toString( T const& value );
+
+// Built in overloads
+
+std::string toString( std::string const& value );
+std::string toString( std::wstring const& value );
+std::string toString( const char* const value );
+std::string toString( char* const value );
+std::string toString( const wchar_t* const value );
+std::string toString( wchar_t* const value );
+std::string toString( int value );
+std::string toString( unsigned long value );
+std::string toString( unsigned int value );
+std::string toString( const double value );
+std::string toString( const float value );
+std::string toString( bool value );
+std::string toString( char value );
+std::string toString( signed char value );
+std::string toString( unsigned char value );
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value );
+std::string toString( unsigned long long value );
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t );
+#endif
+
+#ifdef __OBJC__
+    std::string toString( NSString const * const& nsstring );
+    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
+    std::string toString( NSObject* const& nsObject );
+#endif
+
+namespace Detail {
+
+    extern const std::string unprintableString;
+
+ #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
+    struct BorgType {
+        template<typename T> BorgType( T const& );
+    };
+
+    struct TrueType { char sizer[1]; };
+    struct FalseType { char sizer[2]; };
+
+    TrueType& testStreamable( std::ostream& );
+    FalseType testStreamable( FalseType );
+
+    FalseType operator<<( std::ostream const&, BorgType const& );
+
+    template<typename T>
+    struct IsStreamInsertable {
+        static std::ostream &s;
+        static T  const&t;
+        enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+    };
+#else
+    template<typename T>
+    class IsStreamInsertable {
+        template<typename SS, typename TT>
+        static auto test(int)
+        -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
+
+        template<typename, typename>
+        static auto test(...) -> std::false_type;
+
+    public:
+        static const bool value = decltype(test<std::ostream,const T&>(0))::value;
+    };
+#endif
+
+#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
+    template<typename T,
+             bool IsEnum = std::is_enum<T>::value
+             >
+    struct EnumStringMaker
+    {
+        static std::string convert( T const& ) { return unprintableString; }
+    };
+
+    template<typename T>
+    struct EnumStringMaker<T,true>
+    {
+        static std::string convert( T const& v )
+        {
+            return ::Catch::toString(
+                static_cast<typename std::underlying_type<T>::type>(v)
+                );
+        }
+    };
+#endif
+    template<bool C>
+    struct StringMakerBase {
+#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
+        template<typename T>
+        static std::string convert( T const& v )
+        {
+            return EnumStringMaker<T>::convert( v );
+        }
+#else
+        template<typename T>
+        static std::string convert( T const& ) { return unprintableString; }
+#endif
+    };
+
+    template<>
+    struct StringMakerBase<true> {
+        template<typename T>
+        static std::string convert( T const& _value ) {
+            std::ostringstream oss;
+            oss << _value;
+            return oss.str();
+        }
+    };
+
+    std::string rawMemoryToString( const void *object, std::size_t size );
+
+    template<typename T>
+    inline std::string rawMemoryToString( const T& object ) {
+      return rawMemoryToString( &object, sizeof(object) );
+    }
+
+} // end namespace Detail
+
+template<typename T>
+struct StringMaker :
+    Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+    template<typename U>
+    static std::string convert( U* p ) {
+        if( !p )
+            return "NULL";
+        else
+            return Detail::rawMemoryToString( p );
+    }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+    static std::string convert( R C::* p ) {
+        if( !p )
+            return "NULL";
+        else
+            return Detail::rawMemoryToString( p );
+    }
+};
+
+namespace Detail {
+    template<typename InputIterator>
+    std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+//template<typename T, typename Allocator>
+//struct StringMaker<std::vector<T, Allocator> > {
+//    static std::string convert( std::vector<T,Allocator> const& v ) {
+//        return Detail::rangeToString( v.begin(), v.end() );
+//    }
+//};
+
+template<typename T, typename Allocator>
+std::string toString( std::vector<T,Allocator> const& v ) {
+    return Detail::rangeToString( v.begin(), v.end() );
+}
+
+#ifdef CATCH_CONFIG_CPP11_TUPLE
+
+// toString for tuples
+namespace TupleDetail {
+  template<
+      typename Tuple,
+      std::size_t N = 0,
+      bool = (N < std::tuple_size<Tuple>::value)
+      >
+  struct ElementPrinter {
+      static void print( const Tuple& tuple, std::ostream& os )
+      {
+          os << ( N ? ", " : " " )
+             << Catch::toString(std::get<N>(tuple));
+          ElementPrinter<Tuple,N+1>::print(tuple,os);
+      }
+  };
+
+  template<
+      typename Tuple,
+      std::size_t N
+      >
+  struct ElementPrinter<Tuple,N,false> {
+      static void print( const Tuple&, std::ostream& ) {}
+  };
+
+}
+
+template<typename ...Types>
+struct StringMaker<std::tuple<Types...>> {
+
+    static std::string convert( const std::tuple<Types...>& tuple )
+    {
+        std::ostringstream os;
+        os << '{';
+        TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
+        os << " }";
+        return os.str();
+    }
+};
+#endif // CATCH_CONFIG_CPP11_TUPLE
+
+namespace Detail {
+    template<typename T>
+    std::string makeString( T const& value ) {
+        return StringMaker<T>::convert( value );
+    }
+} // end namespace Detail
+
+/// \brief converts any type to a string
+///
+/// The default template forwards on to ostringstream - except when an
+/// ostringstream overload does not exist - in which case it attempts to detect
+/// that and writes {?}.
+/// Overload (not specialise) this template for custom typs that you don't want
+/// to provide an ostream overload for.
+template<typename T>
+std::string toString( T const& value ) {
+    return StringMaker<T>::convert( value );
+}
+
+    namespace Detail {
+    template<typename InputIterator>
+    std::string rangeToString( InputIterator first, InputIterator last ) {
+        std::ostringstream oss;
+        oss << "{ ";
+        if( first != last ) {
+            oss << Catch::toString( *first );
+            for( ++first ; first != last ; ++first )
+                oss << ", " << Catch::toString( *first );
+        }
+        oss << " }";
+        return oss.str();
+    }
+}
+
+} // end namespace Catch
+
+namespace Catch {
+
+template<typename LhsT, Internal::Operator Op, typename RhsT>
+class BinaryExpression;
+
+template<typename ArgT, typename MatcherT>
+class MatchExpression;
+
+// Wraps the LHS of an expression and overloads comparison operators
+// for also capturing those and RHS (if any)
+template<typename T>
+class ExpressionLhs : public DecomposedExpression {
+public:
+    ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
+
+    ExpressionLhs& operator = ( const ExpressionLhs& );
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
+    operator == ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
+    operator != ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsNotEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsLessThan, RhsT const&>
+    operator < ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsLessThan>( rhs );
+    }
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
+    operator > ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsGreaterThan>( rhs );
+    }
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
+    operator <= ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
+    operator >= ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+    }
+
+    BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
+        return captureExpression<Internal::IsEqualTo>( rhs );
+    }
+
+    BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
+        return captureExpression<Internal::IsNotEqualTo>( rhs );
+    }
+
+    void endExpression() {
+        m_truthy = m_lhs ? true : false;
+        m_rb
+            .setResultType( m_truthy )
+            .endExpression( *this );
+    }
+
+    virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+        dest = Catch::toString( m_truthy );
+    }
+
+private:
+    template<Internal::Operator Op, typename RhsT>
+    BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
+        return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
+    }
+
+    template<Internal::Operator Op>
+    BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
+        return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
+    }
+
+private:
+    ResultBuilder& m_rb;
+    T m_lhs;
+    bool m_truthy;
+};
+
+template<typename LhsT, Internal::Operator Op, typename RhsT>
+class BinaryExpression : public DecomposedExpression {
+public:
+    BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
+        : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
+
+    BinaryExpression& operator = ( BinaryExpression& );
+
+    void endExpression() const {
+        m_rb
+            .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
+            .endExpression( *this );
+    }
+
+    virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+        return true;
+    }
+
+    virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+        std::string lhs = Catch::toString( m_lhs );
+        std::string rhs = Catch::toString( m_rhs );
+        char delim = lhs.size() + rhs.size() < 40 &&
+                     lhs.find('\n') == std::string::npos &&
+                     rhs.find('\n') == std::string::npos ? ' ' : '\n';
+        dest.reserve( 7 + lhs.size() + rhs.size() );
+                   // 2 for spaces around operator
+                   // 2 for operator
+                   // 2 for parentheses (conditionally added later)
+                   // 1 for negation (conditionally added later)
+        dest = lhs;
+        dest += delim;
+        dest += Internal::OperatorTraits<Op>::getName();
+        dest += delim;
+        dest += rhs;
+    }
+
+private:
+    ResultBuilder& m_rb;
+    LhsT m_lhs;
+    RhsT m_rhs;
+};
+
+template<typename ArgT, typename MatcherT>
+class MatchExpression : public DecomposedExpression {
+public:
+    MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
+        : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
+
+    virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+        return true;
+    }
+
+    virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+        std::string matcherAsString = m_matcher.toString();
+        dest = Catch::toString( m_arg );
+        dest += ' ';
+        if( matcherAsString == Detail::unprintableString )
+            dest += m_matcherString;
+        else
+            dest += matcherAsString;
+    }
+
+private:
+    ArgT m_arg;
+    MatcherT m_matcher;
+    char const* m_matcherString;
+};
+
+} // end namespace Catch
+
+
+namespace Catch {
+
+    template<typename T>
+    inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
+        return ExpressionLhs<T const&>( *this, operand );
+    }
+
+    inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
+        return ExpressionLhs<bool>( *this, value );
+    }
+
+    template<typename ArgT, typename MatcherT>
+    inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
+                                             char const* matcherString ) {
+        MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
+        setResultType( matcher.match( arg ) );
+        endExpression( expr );
+    }
+
+} // namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct MessageInfo {
+        MessageInfo(    std::string const& _macroName,
+                        SourceLineInfo const& _lineInfo,
+                        ResultWas::OfType _type );
+
+        std::string macroName;
+        SourceLineInfo lineInfo;
+        ResultWas::OfType type;
+        std::string message;
+        unsigned int sequence;
+
+        bool operator == ( MessageInfo const& other ) const {
+            return sequence == other.sequence;
+        }
+        bool operator < ( MessageInfo const& other ) const {
+            return sequence < other.sequence;
+        }
+    private:
+        static unsigned int globalCount;
+    };
+
+    struct MessageBuilder {
+        MessageBuilder( std::string const& macroName,
+                        SourceLineInfo const& lineInfo,
+                        ResultWas::OfType type )
+        : m_info( macroName, lineInfo, type )
+        {}
+
+        template<typename T>
+        MessageBuilder& operator << ( T const& value ) {
+            m_stream << value;
+            return *this;
+        }
+
+        MessageInfo m_info;
+        std::ostringstream m_stream;
+    };
+
+    class ScopedMessage {
+    public:
+        ScopedMessage( MessageBuilder const& builder );
+        ScopedMessage( ScopedMessage const& other );
+        ~ScopedMessage();
+
+        MessageInfo m_info;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_capture.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    class TestCase;
+    class AssertionResult;
+    struct AssertionInfo;
+    struct SectionInfo;
+    struct SectionEndInfo;
+    struct MessageInfo;
+    class ScopedMessageBuilder;
+    struct Counts;
+
+    struct IResultCapture {
+
+        virtual ~IResultCapture();
+
+        virtual void assertionEnded( AssertionResult const& result ) = 0;
+        virtual bool sectionStarted(    SectionInfo const& sectionInfo,
+                                        Counts& assertions ) = 0;
+        virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
+        virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
+        virtual void pushScopedMessage( MessageInfo const& message ) = 0;
+        virtual void popScopedMessage( MessageInfo const& message ) = 0;
+
+        virtual std::string getCurrentTestName() const = 0;
+        virtual const AssertionResult* getLastResult() const = 0;
+
+        virtual void exceptionEarlyReported() = 0;
+
+        virtual void handleFatalErrorCondition( std::string const& message ) = 0;
+    };
+
+    IResultCapture& getResultCapture();
+}
+
+// #included from: catch_debugger.h
+#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
+
+// #included from: catch_platform.h
+#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
+
+#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+#  define CATCH_PLATFORM_MAC
+#elif  defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#  define CATCH_PLATFORM_IPHONE
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+#  define CATCH_PLATFORM_LINUX
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#  define CATCH_PLATFORM_WINDOWS
+#  if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+#    define CATCH_DEFINES_NOMINMAX
+#  endif
+#  if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+#    define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+#  endif
+#endif
+
+#include <string>
+
+namespace Catch{
+
+    bool isDebuggerActive();
+    void writeToDebugConsole( std::string const& text );
+}
+
+#ifdef CATCH_PLATFORM_MAC
+
+    // The following code snippet based on:
+    // http://cocoawithlove.com/2008/03/break-into-debugger.html
+    #if defined(__ppc64__) || defined(__ppc__)
+        #define CATCH_TRAP() \
+                __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
+                : : : "memory","r0","r3","r4" )
+    #else
+        #define CATCH_TRAP() __asm__("int $3\n" : : )
+    #endif
+
+#elif defined(CATCH_PLATFORM_LINUX)
+    // If we can use inline assembler, do it because this allows us to break
+    // directly at the location of the failing check instead of breaking inside
+    // raise() called from it, i.e. one stack frame below.
+    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+        #define CATCH_TRAP() asm volatile ("int $3")
+    #else // Fall back to the generic way.
+        #include <signal.h>
+
+        #define CATCH_TRAP() raise(SIGTRAP)
+    #endif
+#elif defined(_MSC_VER)
+    #define CATCH_TRAP() __debugbreak()
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+    #define CATCH_TRAP() DebugBreak()
+#endif
+
+#ifdef CATCH_TRAP
+    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
+#else
+    #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
+#endif
+
+// #included from: catch_interfaces_runner.h
+#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
+
+namespace Catch {
+    class TestCase;
+
+    struct IRunner {
+        virtual ~IRunner();
+        virtual bool aborting() const = 0;
+    };
+}
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+///////////////////////////////////////////////////////////////////////////////
+// We can speedup compilation significantly by breaking into debugger lower in
+// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
+// macro in each assertion
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+    resultBuilder.react();
+
+///////////////////////////////////////////////////////////////////////////////
+// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
+// macros.
+// This can potentially cause false negative, if the test code catches
+// the exception before it propagates back up to the runner.
+#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        __catchResult.setExceptionGuard(); \
+        CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+        ( __catchResult <= expr ).endExpression(); \
+        CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+        __catchResult.unsetExceptionGuard(); \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
+// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
+
+#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
+        __catchResult.setExceptionGuard(); \
+        __catchResult.captureMatch( arg, matcher, #matcher ); \
+        __catchResult.unsetExceptionGuard(); \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
+
+#else
+///////////////////////////////////////////////////////////////////////////////
+// In the event of a failure works out if the debugger needs to be invoked
+// and/or an exception thrown and takes appropriate action.
+// This needs to be done as a macro so the debugger will stop in the user
+// source code rather than in Catch library code
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+    if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
+    resultBuilder.react();
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+            ( __catchResult <= expr ).endExpression(); \
+            CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+        } \
+        catch( ... ) { \
+            __catchResult.useActiveException( resultDisposition ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
+    // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
+    INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
+    if( Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
+    INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
+    if( !Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            static_cast<void>(expr); \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
+        } \
+        catch( ... ) { \
+            __catchResult.useActiveException( resultDisposition ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
+        if( __catchResult.allowThrows() ) \
+            try { \
+                static_cast<void>(expr); \
+                __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
+            } \
+            catch( ... ) { \
+                __catchResult.captureExpectedException( matcher ); \
+            } \
+        else \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
+        if( __catchResult.allowThrows() ) \
+            try { \
+                static_cast<void>(expr); \
+                __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
+            } \
+            catch( exceptionType ) { \
+                __catchResult.captureResult( Catch::ResultWas::Ok ); \
+            } \
+            catch( ... ) { \
+                __catchResult.useActiveException( resultDisposition ); \
+            } \
+        else \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
+        do { \
+            Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
+            __catchResult.captureResult( messageType ); \
+            INTERNAL_CATCH_REACT( __catchResult ) \
+        } while( Catch::alwaysFalse() )
+#else
+    #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
+        do { \
+            Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            __catchResult << log + ::Catch::StreamEndStop(); \
+            __catchResult.captureResult( messageType ); \
+            INTERNAL_CATCH_REACT( __catchResult ) \
+        } while( Catch::alwaysFalse() )
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_INFO( macroName, log ) \
+    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
+    do { \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
+        try { \
+            __catchResult.captureMatch( arg, matcher, #matcher ); \
+        } catch( ... ) { \
+            __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
+
+// #included from: internal/catch_section.h
+#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
+
+// #included from: catch_section_info.h
+#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
+
+// #included from: catch_totals.hpp
+#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
+
+#include <cstddef>
+
+namespace Catch {
+
+    struct Counts {
+        Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
+
+        Counts operator - ( Counts const& other ) const {
+            Counts diff;
+            diff.passed = passed - other.passed;
+            diff.failed = failed - other.failed;
+            diff.failedButOk = failedButOk - other.failedButOk;
+            return diff;
+        }
+        Counts& operator += ( Counts const& other ) {
+            passed += other.passed;
+            failed += other.failed;
+            failedButOk += other.failedButOk;
+            return *this;
+        }
+
+        std::size_t total() const {
+            return passed + failed + failedButOk;
+        }
+        bool allPassed() const {
+            return failed == 0 && failedButOk == 0;
+        }
+        bool allOk() const {
+            return failed == 0;
+        }
+
+        std::size_t passed;
+        std::size_t failed;
+        std::size_t failedButOk;
+    };
+
+    struct Totals {
+
+        Totals operator - ( Totals const& other ) const {
+            Totals diff;
+            diff.assertions = assertions - other.assertions;
+            diff.testCases = testCases - other.testCases;
+            return diff;
+        }
+
+        Totals delta( Totals const& prevTotals ) const {
+            Totals diff = *this - prevTotals;
+            if( diff.assertions.failed > 0 )
+                ++diff.testCases.failed;
+            else if( diff.assertions.failedButOk > 0 )
+                ++diff.testCases.failedButOk;
+            else
+                ++diff.testCases.passed;
+            return diff;
+        }
+
+        Totals& operator += ( Totals const& other ) {
+            assertions += other.assertions;
+            testCases += other.testCases;
+            return *this;
+        }
+
+        Counts assertions;
+        Counts testCases;
+    };
+}
+
+#include <string>
+
+namespace Catch {
+
+    struct SectionInfo {
+        SectionInfo
+            (   SourceLineInfo const& _lineInfo,
+                std::string const& _name,
+                std::string const& _description = std::string() );
+
+        std::string name;
+        std::string description;
+        SourceLineInfo lineInfo;
+    };
+
+    struct SectionEndInfo {
+        SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
+        : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
+        {}
+
+        SectionInfo sectionInfo;
+        Counts prevAssertions;
+        double durationInSeconds;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_timer.h
+#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
+
+#ifdef _MSC_VER
+
+namespace Catch {
+    typedef unsigned long long UInt64;
+}
+#else
+#include <stdint.h>
+namespace Catch {
+    typedef uint64_t UInt64;
+}
+#endif
+
+namespace Catch {
+    class Timer {
+    public:
+        Timer() : m_ticks( 0 ) {}
+        void start();
+        unsigned int getElapsedMicroseconds() const;
+        unsigned int getElapsedMilliseconds() const;
+        double getElapsedSeconds() const;
+
+    private:
+        UInt64 m_ticks;
+    };
+
+} // namespace Catch
+
+#include <string>
+
+namespace Catch {
+
+    class Section : NonCopyable {
+    public:
+        Section( SectionInfo const& info );
+        ~Section();
+
+        // This indicates whether the section should be executed or not
+        operator bool() const;
+
+    private:
+        SectionInfo m_info;
+
+        std::string m_name;
+        Counts m_assertions;
+        bool m_sectionIncluded;
+        Timer m_timer;
+    };
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define INTERNAL_CATCH_SECTION( ... ) \
+        if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+#else
+    #define INTERNAL_CATCH_SECTION( name, desc ) \
+        if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
+#endif
+
+// #included from: internal/catch_generators.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
+
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+    virtual ~IGenerator() {}
+    virtual T getValue( std::size_t index ) const = 0;
+    virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+public:
+    BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
+
+    virtual T getValue( std::size_t index ) const {
+        return m_from+static_cast<int>( index );
+    }
+
+    virtual std::size_t size() const {
+        return static_cast<std::size_t>( 1+m_to-m_from );
+    }
+
+private:
+
+    T m_from;
+    T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+public:
+    ValuesGenerator(){}
+
+    void add( T value ) {
+        m_values.push_back( value );
+    }
+
+    virtual T getValue( std::size_t index ) const {
+        return m_values[index];
+    }
+
+    virtual std::size_t size() const {
+        return m_values.size();
+    }
+
+private:
+    std::vector<T> m_values;
+};
+
+template<typename T>
+class CompositeGenerator {
+public:
+    CompositeGenerator() : m_totalSize( 0 ) {}
+
+    // *** Move semantics, similar to auto_ptr ***
+    CompositeGenerator( CompositeGenerator& other )
+    :   m_fileInfo( other.m_fileInfo ),
+        m_totalSize( 0 )
+    {
+        move( other );
+    }
+
+    CompositeGenerator& setFileInfo( const char* fileInfo ) {
+        m_fileInfo = fileInfo;
+        return *this;
+    }
+
+    ~CompositeGenerator() {
+        deleteAll( m_composed );
+    }
+
+    operator T () const {
+        size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
+
+        typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
+        typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+        for( size_t index = 0; it != itEnd; ++it )
+        {
+            const IGenerator<T>* generator = *it;
+            if( overallIndex >= index && overallIndex < index + generator->size() )
+            {
+                return generator->getValue( overallIndex-index );
+            }
+            index += generator->size();
+        }
+        CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
+        return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
+    }
+
+    void add( const IGenerator<T>* generator ) {
+        m_totalSize += generator->size();
+        m_composed.push_back( generator );
+    }
+
+    CompositeGenerator& then( CompositeGenerator& other ) {
+        move( other );
+        return *this;
+    }
+
+    CompositeGenerator& then( T value ) {
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( value );
+        add( valuesGen );
+        return *this;
+    }
+
+private:
+
+    void move( CompositeGenerator& other ) {
+        m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
+        m_totalSize += other.m_totalSize;
+        other.m_composed.clear();
+    }
+
+    std::vector<const IGenerator<T>*> m_composed;
+    std::string m_fileInfo;
+    size_t m_totalSize;
+};
+
+namespace Generators
+{
+    template<typename T>
+    CompositeGenerator<T> between( T from, T to ) {
+        CompositeGenerator<T> generators;
+        generators.add( new BetweenGenerator<T>( from, to ) );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2 ) {
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2, T val3 ){
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        valuesGen->add( val3 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        valuesGen->add( val3 );
+        valuesGen->add( val4 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+} // end namespace Generators
+
+using namespace Generators;
+
+} // end namespace Catch
+
+#define INTERNAL_CATCH_LINESTR2( line ) #line
+#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
+
+#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
+
+// #included from: internal/catch_interfaces_exception.h
+#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
+
+#include <string>
+#include <vector>
+
+// #included from: catch_interfaces_registry_hub.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    class TestCase;
+    struct ITestCaseRegistry;
+    struct IExceptionTranslatorRegistry;
+    struct IExceptionTranslator;
+    struct IReporterRegistry;
+    struct IReporterFactory;
+    struct ITagAliasRegistry;
+
+    struct IRegistryHub {
+        virtual ~IRegistryHub();
+
+        virtual IReporterRegistry const& getReporterRegistry() const = 0;
+        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
+
+        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+    };
+
+    struct IMutableRegistryHub {
+        virtual ~IMutableRegistryHub();
+        virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
+        virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
+        virtual void registerTest( TestCase const& testInfo ) = 0;
+        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
+        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
+    };
+
+    IRegistryHub& getRegistryHub();
+    IMutableRegistryHub& getMutableRegistryHub();
+    void cleanUp();
+    std::string translateActiveException();
+
+}
+
+namespace Catch {
+
+    typedef std::string(*exceptionTranslateFunction)();
+
+    struct IExceptionTranslator;
+    typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
+
+    struct IExceptionTranslator {
+        virtual ~IExceptionTranslator();
+        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
+    };
+
+    struct IExceptionTranslatorRegistry {
+        virtual ~IExceptionTranslatorRegistry();
+
+        virtual std::string translateActiveException() const = 0;
+    };
+
+    class ExceptionTranslatorRegistrar {
+        template<typename T>
+        class ExceptionTranslator : public IExceptionTranslator {
+        public:
+
+            ExceptionTranslator( std::string(*translateFunction)( T& ) )
+            : m_translateFunction( translateFunction )
+            {}
+
+            virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
+                try {
+                    if( it == itEnd )
+                        throw;
+                    else
+                        return (*it)->translate( it+1, itEnd );
+                }
+                catch( T& ex ) {
+                    return m_translateFunction( ex );
+                }
+            }
+
+        protected:
+            std::string(*m_translateFunction)( T& );
+        };
+
+    public:
+        template<typename T>
+        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+            getMutableRegistryHub().registerTranslator
+                ( new ExceptionTranslator<T>( translateFunction ) );
+        }
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
+    static std::string translatorName( signature ); \
+    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
+    static std::string translatorName( signature )
+
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
+
+// #included from: internal/catch_approx.hpp
+#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
+
+#include <cmath>
+#include <limits>
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+#include <type_traits>
+#endif
+
+namespace Catch {
+namespace Detail {
+
+    class Approx {
+    public:
+        explicit Approx ( double value )
+        :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
+            m_margin( 0.0 ),
+            m_scale( 1.0 ),
+            m_value( value )
+        {}
+
+        Approx( Approx const& other )
+        :   m_epsilon( other.m_epsilon ),
+            m_margin( other.m_margin ),
+            m_scale( other.m_scale ),
+            m_value( other.m_value )
+        {}
+
+        static Approx custom() {
+            return Approx( 0 );
+        }
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        Approx operator()( T value ) {
+            Approx approx( static_cast<double>(value) );
+            approx.epsilon( m_epsilon );
+            approx.margin( m_margin );
+            approx.scale( m_scale );
+            return approx;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        explicit Approx( T value ): Approx(static_cast<double>(value))
+        {}
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator == ( const T& lhs, Approx const& rhs ) {
+            // Thanks to Richard Harris for his help refining this formula
+            auto lhs_v = double(lhs);
+            bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
+            if (relativeOK) {
+                return true;
+            }
+            return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator == ( Approx const& lhs, const T& rhs ) {
+            return operator==( rhs, lhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator != ( T lhs, Approx const& rhs ) {
+            return !operator==( lhs, rhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator != ( Approx const& lhs, T rhs ) {
+            return !operator==( rhs, lhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator <= ( T lhs, Approx const& rhs ) {
+            return double(lhs) < rhs.m_value || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator <= ( Approx const& lhs, T rhs ) {
+            return lhs.m_value < double(rhs) || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator >= ( T lhs, Approx const& rhs ) {
+            return double(lhs) > rhs.m_value || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator >= ( Approx const& lhs, T rhs ) {
+            return lhs.m_value > double(rhs) || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        Approx& epsilon( T newEpsilon ) {
+            m_epsilon = double(newEpsilon);
+            return *this;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        Approx& margin( T newMargin ) {
+            m_margin = double(newMargin);
+            return *this;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        Approx& scale( T newScale ) {
+            m_scale = double(newScale);
+            return *this;
+        }
+
+#else
+
+        Approx operator()( double value ) {
+            Approx approx( value );
+            approx.epsilon( m_epsilon );
+            approx.margin( m_margin );
+            approx.scale( m_scale );
+            return approx;
+        }
+
+        friend bool operator == ( double lhs, Approx const& rhs ) {
+            // Thanks to Richard Harris for his help refining this formula
+            bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
+            if (relativeOK) {
+                return true;
+            }
+            return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
+        }
+
+        friend bool operator == ( Approx const& lhs, double rhs ) {
+            return operator==( rhs, lhs );
+        }
+
+        friend bool operator != ( double lhs, Approx const& rhs ) {
+            return !operator==( lhs, rhs );
+        }
+
+        friend bool operator != ( Approx const& lhs, double rhs ) {
+            return !operator==( rhs, lhs );
+        }
+
+        friend bool operator <= ( double lhs, Approx const& rhs ) {
+            return lhs < rhs.m_value || lhs == rhs;
+        }
+
+        friend bool operator <= ( Approx const& lhs, double rhs ) {
+            return lhs.m_value < rhs || lhs == rhs;
+        }
+
+        friend bool operator >= ( double lhs, Approx const& rhs ) {
+            return lhs > rhs.m_value || lhs == rhs;
+        }
+
+        friend bool operator >= ( Approx const& lhs, double rhs ) {
+            return lhs.m_value > rhs || lhs == rhs;
+        }
+
+        Approx& epsilon( double newEpsilon ) {
+            m_epsilon = newEpsilon;
+            return *this;
+        }
+
+        Approx& margin( double newMargin ) {
+            m_margin = newMargin;
+            return *this;
+        }
+
+        Approx& scale( double newScale ) {
+            m_scale = newScale;
+            return *this;
+        }
+#endif
+
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << "Approx( " << Catch::toString( m_value ) << " )";
+            return oss.str();
+        }
+
+    private:
+        double m_epsilon;
+        double m_margin;
+        double m_scale;
+        double m_value;
+    };
+}
+
+template<>
+inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
+    return value.toString();
+}
+
+} // end namespace Catch
+
+// #included from: internal/catch_matchers_string.h
+#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+    namespace StdString {
+
+        struct CasedString
+        {
+            CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
+            std::string adjustString( std::string const& str ) const;
+            std::string caseSensitivitySuffix() const;
+
+            CaseSensitive::Choice m_caseSensitivity;
+            std::string m_str;
+        };
+
+        struct StringMatcherBase : MatcherBase<std::string> {
+            StringMatcherBase( std::string const& operation, CasedString const& comparator );
+            virtual std::string describe() const CATCH_OVERRIDE;
+
+            CasedString m_comparator;
+            std::string m_operation;
+        };
+
+        struct EqualsMatcher : StringMatcherBase {
+            EqualsMatcher( CasedString const& comparator );
+            virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+        };
+        struct ContainsMatcher : StringMatcherBase {
+            ContainsMatcher( CasedString const& comparator );
+            virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+        };
+        struct StartsWithMatcher : StringMatcherBase {
+            StartsWithMatcher( CasedString const& comparator );
+            virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+        };
+        struct EndsWithMatcher : StringMatcherBase {
+            EndsWithMatcher( CasedString const& comparator );
+            virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+        };
+
+    } // namespace StdString
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+
+    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+
+} // namespace Matchers
+} // namespace Catch
+
+// #included from: internal/catch_matchers_vector.h
+#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+    namespace Vector {
+
+        template<typename T>
+        struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
+
+            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
+
+            bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+                return std::find(v.begin(), v.end(), m_comparator) != v.end();
+            }
+
+            virtual std::string describe() const CATCH_OVERRIDE {
+                return "Contains: " + Catch::toString( m_comparator );
+            }
+
+            T const& m_comparator;
+        };
+
+        template<typename T>
+        struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
+
+            ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+            bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+                // !TBD: see note in EqualsMatcher
+                if (m_comparator.size() > v.size())
+                    return false;
+                for (size_t i = 0; i < m_comparator.size(); ++i)
+                    if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
+                        return false;
+                return true;
+            }
+            virtual std::string describe() const CATCH_OVERRIDE {
+                return "Contains: " + Catch::toString( m_comparator );
+            }
+
+            std::vector<T> const& m_comparator;
+        };
+
+        template<typename T>
+        struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
+
+            EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+            bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+                // !TBD: This currently works if all elements can be compared using !=
+                // - a more general approach would be via a compare template that defaults
+                // to using !=. but could be specialised for, e.g. std::vector<T> etc
+                // - then just call that directly
+                if (m_comparator.size() != v.size())
+                    return false;
+                for (size_t i = 0; i < v.size(); ++i)
+                    if (m_comparator[i] != v[i])
+                        return false;
+                return true;
+            }
+            virtual std::string describe() const CATCH_OVERRIDE {
+                return "Equals: " + Catch::toString( m_comparator );
+            }
+            std::vector<T> const& m_comparator;
+        };
+
+    } // namespace Vector
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+
+    template<typename T>
+    Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
+        return Vector::ContainsMatcher<T>( comparator );
+    }
+
+    template<typename T>
+    Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
+        return Vector::ContainsElementMatcher<T>( comparator );
+    }
+
+    template<typename T>
+    Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
+        return Vector::EqualsMatcher<T>( comparator );
+    }
+
+} // namespace Matchers
+} // namespace Catch
+
+// #included from: internal/catch_interfaces_tag_alias_registry.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
+
+// #included from: catch_tag_alias.h
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct TagAlias {
+        TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
+
+        std::string tag;
+        SourceLineInfo lineInfo;
+    };
+
+    struct RegistrarForTagAliases {
+        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+    };
+
+} // end namespace Catch
+
+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
+// #included from: catch_option.hpp
+#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
+
+namespace Catch {
+
+    // An optional type
+    template<typename T>
+    class Option {
+    public:
+        Option() : nullableValue( CATCH_NULL ) {}
+        Option( T const& _value )
+        : nullableValue( new( storage ) T( _value ) )
+        {}
+        Option( Option const& _other )
+        : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
+        {}
+
+        ~Option() {
+            reset();
+        }
+
+        Option& operator= ( Option const& _other ) {
+            if( &_other != this ) {
+                reset();
+                if( _other )
+                    nullableValue = new( storage ) T( *_other );
+            }
+            return *this;
+        }
+        Option& operator = ( T const& _value ) {
+            reset();
+            nullableValue = new( storage ) T( _value );
+            return *this;
+        }
+
+        void reset() {
+            if( nullableValue )
+                nullableValue->~T();
+            nullableValue = CATCH_NULL;
+        }
+
+        T& operator*() { return *nullableValue; }
+        T const& operator*() const { return *nullableValue; }
+        T* operator->() { return nullableValue; }
+        const T* operator->() const { return nullableValue; }
+
+        T valueOr( T const& defaultValue ) const {
+            return nullableValue ? *nullableValue : defaultValue;
+        }
+
+        bool some() const { return nullableValue != CATCH_NULL; }
+        bool none() const { return nullableValue == CATCH_NULL; }
+
+        bool operator !() const { return nullableValue == CATCH_NULL; }
+        operator SafeBool::type() const {
+            return SafeBool::makeSafe( some() );
+        }
+
+    private:
+        T *nullableValue;
+        union {
+            char storage[sizeof(T)];
+
+            // These are here to force alignment for the storage
+            long double dummy1;
+            void (*dummy2)();
+            long double dummy3;
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+            long long dummy4;
+#endif
+        };
+    };
+
+} // end namespace Catch
+
+namespace Catch {
+
+    struct ITagAliasRegistry {
+        virtual ~ITagAliasRegistry();
+        virtual Option<TagAlias> find( std::string const& alias ) const = 0;
+        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
+
+        static ITagAliasRegistry const& get();
+    };
+
+} // end namespace Catch
+
+// These files are included here so the single_include script doesn't put them
+// in the conditionally compiled sections
+// #included from: internal/catch_test_case_info.h
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
+
+#include <string>
+#include <set>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    struct ITestCase;
+
+    struct TestCaseInfo {
+        enum SpecialProperties{
+            None = 0,
+            IsHidden = 1 << 1,
+            ShouldFail = 1 << 2,
+            MayFail = 1 << 3,
+            Throws = 1 << 4,
+            NonPortable = 1 << 5
+        };
+
+        TestCaseInfo(   std::string const& _name,
+                        std::string const& _className,
+                        std::string const& _description,
+                        std::set<std::string> const& _tags,
+                        SourceLineInfo const& _lineInfo );
+
+        TestCaseInfo( TestCaseInfo const& other );
+
+        friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
+
+        bool isHidden() const;
+        bool throws() const;
+        bool okToFail() const;
+        bool expectedToFail() const;
+
+        std::string name;
+        std::string className;
+        std::string description;
+        std::set<std::string> tags;
+        std::set<std::string> lcaseTags;
+        std::string tagsAsString;
+        SourceLineInfo lineInfo;
+        SpecialProperties properties;
+    };
+
+    class TestCase : public TestCaseInfo {
+    public:
+
+        TestCase( ITestCase* testCase, TestCaseInfo const& info );
+        TestCase( TestCase const& other );
+
+        TestCase withName( std::string const& _newName ) const;
+
+        void invoke() const;
+
+        TestCaseInfo const& getTestCaseInfo() const;
+
+        void swap( TestCase& other );
+        bool operator == ( TestCase const& other ) const;
+        bool operator < ( TestCase const& other ) const;
+        TestCase& operator = ( TestCase const& other );
+
+    private:
+        Ptr<ITestCase> test;
+    };
+
+    TestCase makeTestCase(  ITestCase* testCase,
+                            std::string const& className,
+                            std::string const& name,
+                            std::string const& description,
+                            SourceLineInfo const& lineInfo );
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+
+#ifdef __OBJC__
+// #included from: internal/catch_objc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
+
+#import <objc/runtime.h>
+
+#include <string>
+
+// NB. Any general catch headers included here must be included
+// in catch.hpp first to make sure they are included by the single
+// header for non obj-usage
+
+///////////////////////////////////////////////////////////////////////////////
+// This protocol is really only here for (self) documenting purposes, since
+// all its methods are optional.
+@protocol OcFixture
+
+@optional
+
+-(void) setUp;
+-(void) tearDown;
+
+@end
+
+namespace Catch {
+
+    class OcMethod : public SharedImpl<ITestCase> {
+
+    public:
+        OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
+
+        virtual void invoke() const {
+            id obj = [[m_cls alloc] init];
+
+            performOptionalSelector( obj, @selector(setUp)  );
+            performOptionalSelector( obj, m_sel );
+            performOptionalSelector( obj, @selector(tearDown)  );
+
+            arcSafeRelease( obj );
+        }
+    private:
+        virtual ~OcMethod() {}
+
+        Class m_cls;
+        SEL m_sel;
+    };
+
+    namespace Detail{
+
+        inline std::string getAnnotation(   Class cls,
+                                            std::string const& annotationName,
+                                            std::string const& testCaseName ) {
+            NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
+            SEL sel = NSSelectorFromString( selStr );
+            arcSafeRelease( selStr );
+            id value = performOptionalSelector( cls, sel );
+            if( value )
+                return [(NSString*)value UTF8String];
+            return "";
+        }
+    }
+
+    inline size_t registerTestMethods() {
+        size_t noTestMethods = 0;
+        int noClasses = objc_getClassList( CATCH_NULL, 0 );
+
+        Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
+        objc_getClassList( classes, noClasses );
+
+        for( int c = 0; c < noClasses; c++ ) {
+            Class cls = classes[c];
+            {
+                u_int count;
+                Method* methods = class_copyMethodList( cls, &count );
+                for( u_int m = 0; m < count ; m++ ) {
+                    SEL selector = method_getName(methods[m]);
+                    std::string methodName = sel_getName(selector);
+                    if( startsWith( methodName, "Catch_TestCase_" ) ) {
+                        std::string testCaseName = methodName.substr( 15 );
+                        std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
+                        std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
+                        const char* className = class_getName( cls );
+
+                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
+                        noTestMethods++;
+                    }
+                }
+                free(methods);
+            }
+        }
+        return noTestMethods;
+    }
+
+    namespace Matchers {
+        namespace Impl {
+        namespace NSStringMatchers {
+
+            struct StringHolder : MatcherBase<NSString*>{
+                StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
+                StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
+                StringHolder() {
+                    arcSafeRelease( m_substr );
+                }
+
+                virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
+                    return false;
+                }
+
+                NSString* m_substr;
+            };
+
+            struct Equals : StringHolder {
+                Equals( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( NSString* str ) const CATCH_OVERRIDE {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str isEqualToString:m_substr];
+                }
+
+                virtual std::string describe() const CATCH_OVERRIDE {
+                    return "equals string: " + Catch::toString( m_substr );
+                }
+            };
+
+            struct Contains : StringHolder {
+                Contains( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( NSString* str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location != NSNotFound;
+                }
+
+                virtual std::string describe() const CATCH_OVERRIDE {
+                    return "contains string: " + Catch::toString( m_substr );
+                }
+            };
+
+            struct StartsWith : StringHolder {
+                StartsWith( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( NSString* str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == 0;
+                }
+
+                virtual std::string describe() const CATCH_OVERRIDE {
+                    return "starts with: " + Catch::toString( m_substr );
+                }
+            };
+            struct EndsWith : StringHolder {
+                EndsWith( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( NSString* str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == [str length] - [m_substr length];
+                }
+
+                virtual std::string describe() const CATCH_OVERRIDE {
+                    return "ends with: " + Catch::toString( m_substr );
+                }
+            };
+
+        } // namespace NSStringMatchers
+        } // namespace Impl
+
+        inline Impl::NSStringMatchers::Equals
+            Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
+
+        inline Impl::NSStringMatchers::Contains
+            Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
+
+        inline Impl::NSStringMatchers::StartsWith
+            StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
+
+        inline Impl::NSStringMatchers::EndsWith
+            EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
+
+    } // namespace Matchers
+
+    using namespace Matchers;
+
+} // namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define OC_TEST_CASE( name, desc )\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
+{\
+return @ name; \
+}\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
+{ \
+return @ desc; \
+} \
+-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
+
+#endif
+
+#ifdef CATCH_IMPL
+
+// !TBD: Move the leak detector code into a separate header
+#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
+#include <crtdbg.h>
+class LeakDetector {
+public:
+	LeakDetector() {
+		int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+		flag |= _CRTDBG_LEAK_CHECK_DF;
+		flag |= _CRTDBG_ALLOC_MEM_DF;
+		_CrtSetDbgFlag(flag);
+		_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+		_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+		// Change this to leaking allocation's number to break there
+		_CrtSetBreakAlloc(-1);
+	}
+};
+#else
+class LeakDetector {};
+#endif
+
+LeakDetector leakDetector;
+
+// #included from: internal/catch_impl.hpp
+#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
+
+// Collect all the implementation files together here
+// These are the equivalent of what would usually be cpp files
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+// #included from: ../catch_session.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+
+// #included from: internal/catch_commandline.hpp
+#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+
+// #included from: catch_config.hpp
+#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
+
+// #included from: catch_test_spec_parser.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// #included from: catch_test_spec.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// #included from: catch_wildcard_pattern.hpp
+#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
+
+#include <stdexcept>
+
+namespace Catch
+{
+    class WildcardPattern {
+        enum WildcardPosition {
+            NoWildcard = 0,
+            WildcardAtStart = 1,
+            WildcardAtEnd = 2,
+            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+        };
+
+    public:
+
+        WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
+        :   m_caseSensitivity( caseSensitivity ),
+            m_wildcard( NoWildcard ),
+            m_pattern( adjustCase( pattern ) )
+        {
+            if( startsWith( m_pattern, '*' ) ) {
+                m_pattern = m_pattern.substr( 1 );
+                m_wildcard = WildcardAtStart;
+            }
+            if( endsWith( m_pattern, '*' ) ) {
+                m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
+                m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
+            }
+        }
+        virtual ~WildcardPattern();
+        virtual bool matches( std::string const& str ) const {
+            switch( m_wildcard ) {
+                case NoWildcard:
+                    return m_pattern == adjustCase( str );
+                case WildcardAtStart:
+                    return endsWith( adjustCase( str ), m_pattern );
+                case WildcardAtEnd:
+                    return startsWith( adjustCase( str ), m_pattern );
+                case WildcardAtBothEnds:
+                    return contains( adjustCase( str ), m_pattern );
+            }
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+            throw std::logic_error( "Unknown enum" );
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+        }
+    private:
+        std::string adjustCase( std::string const& str ) const {
+            return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
+        }
+        CaseSensitive::Choice m_caseSensitivity;
+        WildcardPosition m_wildcard;
+        std::string m_pattern;
+    };
+}
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    class TestSpec {
+        struct Pattern : SharedImpl<> {
+            virtual ~Pattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const = 0;
+        };
+        class NamePattern : public Pattern {
+        public:
+            NamePattern( std::string const& name )
+            : m_wildcardPattern( toLower( name ), CaseSensitive::No )
+            {}
+            virtual ~NamePattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const {
+                return m_wildcardPattern.matches( toLower( testCase.name ) );
+            }
+        private:
+            WildcardPattern m_wildcardPattern;
+        };
+
+        class TagPattern : public Pattern {
+        public:
+            TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
+            virtual ~TagPattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const {
+                return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
+            }
+        private:
+            std::string m_tag;
+        };
+
+        class ExcludedPattern : public Pattern {
+        public:
+            ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+            virtual ~ExcludedPattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+        private:
+            Ptr<Pattern> m_underlyingPattern;
+        };
+
+        struct Filter {
+            std::vector<Ptr<Pattern> > m_patterns;
+
+            bool matches( TestCaseInfo const& testCase ) const {
+                // All patterns in a filter must match for the filter to be a match
+                for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
+                    if( !(*it)->matches( testCase ) )
+                        return false;
+                }
+                return true;
+            }
+        };
+
+    public:
+        bool hasFilters() const {
+            return !m_filters.empty();
+        }
+        bool matches( TestCaseInfo const& testCase ) const {
+            // A TestSpec matches if any filter matches
+            for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
+                if( it->matches( testCase ) )
+                    return true;
+            return false;
+        }
+
+    private:
+        std::vector<Filter> m_filters;
+
+        friend class TestSpecParser;
+    };
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+namespace Catch {
+
+    class TestSpecParser {
+        enum Mode{ None, Name, QuotedName, Tag, EscapedName };
+        Mode m_mode;
+        bool m_exclusion;
+        std::size_t m_start, m_pos;
+        std::string m_arg;
+        std::vector<std::size_t> m_escapeChars;
+        TestSpec::Filter m_currentFilter;
+        TestSpec m_testSpec;
+        ITagAliasRegistry const* m_tagAliases;
+
+    public:
+        TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
+
+        TestSpecParser& parse( std::string const& arg ) {
+            m_mode = None;
+            m_exclusion = false;
+            m_start = std::string::npos;
+            m_arg = m_tagAliases->expandAliases( arg );
+            m_escapeChars.clear();
+            for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
+                visitChar( m_arg[m_pos] );
+            if( m_mode == Name )
+                addPattern<TestSpec::NamePattern>();
+            return *this;
+        }
+        TestSpec testSpec() {
+            addFilter();
+            return m_testSpec;
+        }
+    private:
+        void visitChar( char c ) {
+            if( m_mode == None ) {
+                switch( c ) {
+                case ' ': return;
+                case '~': m_exclusion = true; return;
+                case '[': return startNewMode( Tag, ++m_pos );
+                case '"': return startNewMode( QuotedName, ++m_pos );
+                case '\\': return escape();
+                default: startNewMode( Name, m_pos ); break;
+                }
+            }
+            if( m_mode == Name ) {
+                if( c == ',' ) {
+                    addPattern<TestSpec::NamePattern>();
+                    addFilter();
+                }
+                else if( c == '[' ) {
+                    if( subString() == "exclude:" )
+                        m_exclusion = true;
+                    else
+                        addPattern<TestSpec::NamePattern>();
+                    startNewMode( Tag, ++m_pos );
+                }
+                else if( c == '\\' )
+                    escape();
+            }
+            else if( m_mode == EscapedName )
+                m_mode = Name;
+            else if( m_mode == QuotedName && c == '"' )
+                addPattern<TestSpec::NamePattern>();
+            else if( m_mode == Tag && c == ']' )
+                addPattern<TestSpec::TagPattern>();
+        }
+        void startNewMode( Mode mode, std::size_t start ) {
+            m_mode = mode;
+            m_start = start;
+        }
+        void escape() {
+            if( m_mode == None )
+                m_start = m_pos;
+            m_mode = EscapedName;
+            m_escapeChars.push_back( m_pos );
+        }
+        std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
+        template<typename T>
+        void addPattern() {
+            std::string token = subString();
+            for( size_t i = 0; i < m_escapeChars.size(); ++i )
+                token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
+            m_escapeChars.clear();
+            if( startsWith( token, "exclude:" ) ) {
+                m_exclusion = true;
+                token = token.substr( 8 );
+            }
+            if( !token.empty() ) {
+                Ptr<TestSpec::Pattern> pattern = new T( token );
+                if( m_exclusion )
+                    pattern = new TestSpec::ExcludedPattern( pattern );
+                m_currentFilter.m_patterns.push_back( pattern );
+            }
+            m_exclusion = false;
+            m_mode = None;
+        }
+        void addFilter() {
+            if( !m_currentFilter.m_patterns.empty() ) {
+                m_testSpec.m_filters.push_back( m_currentFilter );
+                m_currentFilter = TestSpec::Filter();
+            }
+        }
+    };
+    inline TestSpec parseTestSpec( std::string const& arg ) {
+        return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
+    }
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// #included from: catch_interfaces_config.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    struct Verbosity { enum Level {
+        NoOutput = 0,
+        Quiet,
+        Normal
+    }; };
+
+    struct WarnAbout { enum What {
+        Nothing = 0x00,
+        NoAssertions = 0x01
+    }; };
+
+    struct ShowDurations { enum OrNot {
+        DefaultForReporter,
+        Always,
+        Never
+    }; };
+    struct RunTests { enum InWhatOrder {
+        InDeclarationOrder,
+        InLexicographicalOrder,
+        InRandomOrder
+    }; };
+    struct UseColour { enum YesOrNo {
+        Auto,
+        Yes,
+        No
+    }; };
+
+    class TestSpec;
+
+    struct IConfig : IShared {
+
+        virtual ~IConfig();
+
+        virtual bool allowThrows() const = 0;
+        virtual std::ostream& stream() const = 0;
+        virtual std::string name() const = 0;
+        virtual bool includeSuccessfulResults() const = 0;
+        virtual bool shouldDebugBreak() const = 0;
+        virtual bool warnAboutMissingAssertions() const = 0;
+        virtual int abortAfter() const = 0;
+        virtual bool showInvisibles() const = 0;
+        virtual ShowDurations::OrNot showDurations() const = 0;
+        virtual TestSpec const& testSpec() const = 0;
+        virtual RunTests::InWhatOrder runOrder() const = 0;
+        virtual unsigned int rngSeed() const = 0;
+        virtual UseColour::YesOrNo useColour() const = 0;
+        virtual std::vector<std::string> const& getSectionsToRun() const = 0;
+
+    };
+}
+
+// #included from: catch_stream.h
+#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
+
+// #included from: catch_streambuf.h
+#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
+
+#include <streambuf>
+
+namespace Catch {
+
+    class StreamBufBase : public std::streambuf {
+    public:
+        virtual ~StreamBufBase() CATCH_NOEXCEPT;
+    };
+}
+
+#include <streambuf>
+#include <ostream>
+#include <fstream>
+#include <memory>
+
+namespace Catch {
+
+    std::ostream& cout();
+    std::ostream& cerr();
+
+    struct IStream {
+        virtual ~IStream() CATCH_NOEXCEPT;
+        virtual std::ostream& stream() const = 0;
+    };
+
+    class FileStream : public IStream {
+        mutable std::ofstream m_ofs;
+    public:
+        FileStream( std::string const& filename );
+        virtual ~FileStream() CATCH_NOEXCEPT;
+    public: // IStream
+        virtual std::ostream& stream() const CATCH_OVERRIDE;
+    };
+
+    class CoutStream : public IStream {
+        mutable std::ostream m_os;
+    public:
+        CoutStream();
+        virtual ~CoutStream() CATCH_NOEXCEPT;
+
+    public: // IStream
+        virtual std::ostream& stream() const CATCH_OVERRIDE;
+    };
+
+    class DebugOutStream : public IStream {
+        CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
+        mutable std::ostream m_os;
+    public:
+        DebugOutStream();
+        virtual ~DebugOutStream() CATCH_NOEXCEPT;
+
+    public: // IStream
+        virtual std::ostream& stream() const CATCH_OVERRIDE;
+    };
+}
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <stdexcept>
+
+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
+#define CATCH_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+namespace Catch {
+
+    struct ConfigData {
+
+        ConfigData()
+        :   listTests( false ),
+            listTags( false ),
+            listReporters( false ),
+            listTestNamesOnly( false ),
+            showSuccessfulTests( false ),
+            shouldDebugBreak( false ),
+            noThrow( false ),
+            showHelp( false ),
+            showInvisibles( false ),
+            filenamesAsTags( false ),
+            abortAfter( -1 ),
+            rngSeed( 0 ),
+            verbosity( Verbosity::Normal ),
+            warnings( WarnAbout::Nothing ),
+            showDurations( ShowDurations::DefaultForReporter ),
+            runOrder( RunTests::InDeclarationOrder ),
+            useColour( UseColour::Auto )
+        {}
+
+        bool listTests;
+        bool listTags;
+        bool listReporters;
+        bool listTestNamesOnly;
+
+        bool showSuccessfulTests;
+        bool shouldDebugBreak;
+        bool noThrow;
+        bool showHelp;
+        bool showInvisibles;
+        bool filenamesAsTags;
+
+        int abortAfter;
+        unsigned int rngSeed;
+
+        Verbosity::Level verbosity;
+        WarnAbout::What warnings;
+        ShowDurations::OrNot showDurations;
+        RunTests::InWhatOrder runOrder;
+        UseColour::YesOrNo useColour;
+
+        std::string outputFilename;
+        std::string name;
+        std::string processName;
+
+        std::vector<std::string> reporterNames;
+        std::vector<std::string> testsOrTags;
+        std::vector<std::string> sectionsToRun;
+    };
+
+    class Config : public SharedImpl<IConfig> {
+    private:
+        Config( Config const& other );
+        Config& operator = ( Config const& other );
+        virtual void dummy();
+    public:
+
+        Config()
+        {}
+
+        Config( ConfigData const& data )
+        :   m_data( data ),
+            m_stream( openStream() )
+        {
+            if( !data.testsOrTags.empty() ) {
+                TestSpecParser parser( ITagAliasRegistry::get() );
+                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
+                    parser.parse( data.testsOrTags[i] );
+                m_testSpec = parser.testSpec();
+            }
+        }
+
+        virtual ~Config() {}
+
+        std::string const& getFilename() const {
+            return m_data.outputFilename ;
+        }
+
+        bool listTests() const { return m_data.listTests; }
+        bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
+        bool listTags() const { return m_data.listTags; }
+        bool listReporters() const { return m_data.listReporters; }
+
+        std::string getProcessName() const { return m_data.processName; }
+
+        std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
+        std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
+
+        virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
+
+        bool showHelp() const { return m_data.showHelp; }
+
+        // IConfig interface
+        virtual bool allowThrows() const CATCH_OVERRIDE                 { return !m_data.noThrow; }
+        virtual std::ostream& stream() const CATCH_OVERRIDE             { return m_stream->stream(); }
+        virtual std::string name() const CATCH_OVERRIDE                 { return m_data.name.empty() ? m_data.processName : m_data.name; }
+        virtual bool includeSuccessfulResults() const CATCH_OVERRIDE    { return m_data.showSuccessfulTests; }
+        virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE  { return m_data.warnings & WarnAbout::NoAssertions; }
+        virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
+        virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE   { return m_data.runOrder; }
+        virtual unsigned int rngSeed() const CATCH_OVERRIDE             { return m_data.rngSeed; }
+        virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE     { return m_data.useColour; }
+        virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
+        virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
+        virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
+
+    private:
+
+        IStream const* openStream() {
+            if( m_data.outputFilename.empty() )
+                return new CoutStream();
+            else if( m_data.outputFilename[0] == '%' ) {
+                if( m_data.outputFilename == "%debug" )
+                    return new DebugOutStream();
+                else
+                    throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
+            }
+            else
+                return new FileStream( m_data.outputFilename );
+        }
+        ConfigData m_data;
+
+        CATCH_AUTO_PTR( IStream const ) m_stream;
+        TestSpec m_testSpec;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_clara.h
+#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
+
+// Use Catch's value for console width (store Clara's off to the side, if present)
+#ifdef CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
+#undef CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+// Declare Clara inside the Catch namespace
+#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
+// #included from: ../external/clara.h
+
+// Version 0.0.2.4
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
+
+#ifndef STITCH_CLARA_OPEN_NAMESPACE
+#define TWOBLUECUBES_CLARA_H_INCLUDED
+#define STITCH_CLARA_OPEN_NAMESPACE
+#define STITCH_CLARA_CLOSE_NAMESPACE
+#else
+#define STITCH_CLARA_CLOSE_NAMESPACE }
+#endif
+
+#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
+
+// ----------- #included from tbc_text_format.h -----------
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
+#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+#define TBC_TEXT_FORMAT_H_INCLUDED
+#endif
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <cctype>
+
+// Use optional outer namespace
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+    struct TextAttributes {
+        TextAttributes()
+        :   initialIndent( std::string::npos ),
+            indent( 0 ),
+            width( consoleWidth-1 ),
+            tabChar( '\t' )
+        {}
+
+        TextAttributes& setInitialIndent( std::size_t _value )  { initialIndent = _value; return *this; }
+        TextAttributes& setIndent( std::size_t _value )         { indent = _value; return *this; }
+        TextAttributes& setWidth( std::size_t _value )          { width = _value; return *this; }
+        TextAttributes& setTabChar( char _value )               { tabChar = _value; return *this; }
+
+        std::size_t initialIndent;  // indent of first line, or npos
+        std::size_t indent;         // indent of subsequent lines, or all if initialIndent is npos
+        std::size_t width;          // maximum width of text, including indent. Longer text will wrap
+        char tabChar;               // If this char is seen the indent is changed to current pos
+    };
+
+    class Text {
+    public:
+        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+        : attr( _attr )
+        {
+            std::string wrappableChars = " [({.,/|\\-";
+            std::size_t indent = _attr.initialIndent != std::string::npos
+                ? _attr.initialIndent
+                : _attr.indent;
+            std::string remainder = _str;
+
+            while( !remainder.empty() ) {
+                if( lines.size() >= 1000 ) {
+                    lines.push_back( "... message truncated due to excessive size" );
+                    return;
+                }
+                std::size_t tabPos = std::string::npos;
+                std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+                std::size_t pos = remainder.find_first_of( '\n' );
+                if( pos <= width ) {
+                    width = pos;
+                }
+                pos = remainder.find_last_of( _attr.tabChar, width );
+                if( pos != std::string::npos ) {
+                    tabPos = pos;
+                    if( remainder[width] == '\n' )
+                        width--;
+                    remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+                }
+
+                if( width == remainder.size() ) {
+                    spliceLine( indent, remainder, width );
+                }
+                else if( remainder[width] == '\n' ) {
+                    spliceLine( indent, remainder, width );
+                    if( width <= 1 || remainder.size() != 1 )
+                        remainder = remainder.substr( 1 );
+                    indent = _attr.indent;
+                }
+                else {
+                    pos = remainder.find_last_of( wrappableChars, width );
+                    if( pos != std::string::npos && pos > 0 ) {
+                        spliceLine( indent, remainder, pos );
+                        if( remainder[0] == ' ' )
+                            remainder = remainder.substr( 1 );
+                    }
+                    else {
+                        spliceLine( indent, remainder, width-1 );
+                        lines.back() += "-";
+                    }
+                    if( lines.size() == 1 )
+                        indent = _attr.indent;
+                    if( tabPos != std::string::npos )
+                        indent += tabPos;
+                }
+            }
+        }
+
+        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+            lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+            _remainder = _remainder.substr( _pos );
+        }
+
+        typedef std::vector<std::string>::const_iterator const_iterator;
+
+        const_iterator begin() const { return lines.begin(); }
+        const_iterator end() const { return lines.end(); }
+        std::string const& last() const { return lines.back(); }
+        std::size_t size() const { return lines.size(); }
+        std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << *this;
+            return oss.str();
+        }
+
+        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+            for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+                it != itEnd; ++it ) {
+                if( it != _text.begin() )
+                    _stream << "\n";
+                _stream << *it;
+            }
+            return _stream;
+        }
+
+    private:
+        std::string str;
+        TextAttributes attr;
+        std::vector<std::string> lines;
+    };
+
+} // end namespace Tbc
+
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TBC_TEXT_FORMAT_H_INCLUDED
+
+// ----------- end of #include from tbc_text_format.h -----------
+// ........... back in clara.h
+
+#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
+
+// ----------- #included from clara_compilers.h -----------
+
+#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+
+// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
+// The following features are defined:
+//
+// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
+// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
+// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
+// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
+// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
+
+// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
+
+// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
+
+// In general each macro has a _NO_<feature name> form
+// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
+
+#ifdef __clang__
+
+#if __has_feature(cxx_nullptr)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+#if __has_feature(cxx_noexcept)
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+// - otherwise more recent versions define __cplusplus >= 201103L
+// and will get picked up below
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#if (_MSC_VER >= 1600)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#endif
+
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// catch all support for C++11
+#if defined(__cplusplus) && __cplusplus >= 201103L
+
+#define CLARA_CPP11_OR_GREATER
+
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#endif
+
+#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#endif
+
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
+#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
+#endif
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
+#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#endif // __cplusplus >= 201103L
+
+// Now set the actual defines based on the above + anything the user has configured
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_NULLPTR
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_NOEXCEPT
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_GENERATED_METHODS
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_OVERRIDE
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+// noexcept support:
+#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
+#define CLARA_NOEXCEPT noexcept
+#  define CLARA_NOEXCEPT_IS(x) noexcept(x)
+#else
+#define CLARA_NOEXCEPT throw()
+#  define CLARA_NOEXCEPT_IS(x)
+#endif
+
+// nullptr support
+#ifdef CLARA_CONFIG_CPP11_NULLPTR
+#define CLARA_NULL nullptr
+#else
+#define CLARA_NULL NULL
+#endif
+
+// override support
+#ifdef CLARA_CONFIG_CPP11_OVERRIDE
+#define CLARA_OVERRIDE override
+#else
+#define CLARA_OVERRIDE
+#endif
+
+// unique_ptr support
+#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
+#   define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
+#else
+#   define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
+#endif
+
+#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+
+// ----------- end of #include from clara_compilers.h -----------
+// ........... back in clara.h
+
+#include <map>
+#include <stdexcept>
+#include <memory>
+
+#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#define CLARA_PLATFORM_WINDOWS
+#endif
+
+// Use optional outer namespace
+#ifdef STITCH_CLARA_OPEN_NAMESPACE
+STITCH_CLARA_OPEN_NAMESPACE
+#endif
+
+namespace Clara {
+
+    struct UnpositionalTag {};
+
+    extern UnpositionalTag _;
+
+#ifdef CLARA_CONFIG_MAIN
+    UnpositionalTag _;
+#endif
+
+    namespace Detail {
+
+#ifdef CLARA_CONSOLE_WIDTH
+    const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+        using namespace Tbc;
+
+        inline bool startsWith( std::string const& str, std::string const& prefix ) {
+            return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
+        }
+
+        template<typename T> struct RemoveConstRef{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+        template<typename T>    struct IsBool       { static const bool value = false; };
+        template<>              struct IsBool<bool> { static const bool value = true; };
+
+        template<typename T>
+        void convertInto( std::string const& _source, T& _dest ) {
+            std::stringstream ss;
+            ss << _source;
+            ss >> _dest;
+            if( ss.fail() )
+                throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
+        }
+        inline void convertInto( std::string const& _source, std::string& _dest ) {
+            _dest = _source;
+        }
+        char toLowerCh(char c) {
+            return static_cast<char>( std::tolower( c ) );
+        }
+        inline void convertInto( std::string const& _source, bool& _dest ) {
+            std::string sourceLC = _source;
+            std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
+            if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
+                _dest = true;
+            else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
+                _dest = false;
+            else
+                throw std::runtime_error( "Expected a boolean value but did not recognise:\n  '" + _source + "'" );
+        }
+
+        template<typename ConfigT>
+        struct IArgFunction {
+            virtual ~IArgFunction() {}
+#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
+            IArgFunction()                      = default;
+            IArgFunction( IArgFunction const& ) = default;
+#endif
+            virtual void set( ConfigT& config, std::string const& value ) const = 0;
+            virtual bool takesArg() const = 0;
+            virtual IArgFunction* clone() const = 0;
+        };
+
+        template<typename ConfigT>
+        class BoundArgFunction {
+        public:
+            BoundArgFunction() : functionObj( CLARA_NULL ) {}
+            BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+            BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
+            BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+                IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
+                delete functionObj;
+                functionObj = newFunctionObj;
+                return *this;
+            }
+            ~BoundArgFunction() { delete functionObj; }
+
+            void set( ConfigT& config, std::string const& value ) const {
+                functionObj->set( config, value );
+            }
+            bool takesArg() const { return functionObj->takesArg(); }
+
+            bool isSet() const {
+                return functionObj != CLARA_NULL;
+            }
+        private:
+            IArgFunction<ConfigT>* functionObj;
+        };
+
+        template<typename C>
+        struct NullBinder : IArgFunction<C>{
+            virtual void set( C&, std::string const& ) const {}
+            virtual bool takesArg() const { return true; }
+            virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+        };
+
+        template<typename C, typename M>
+        struct BoundDataMember : IArgFunction<C>{
+            BoundDataMember( M C::* _member ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                convertInto( stringValue, p.*member );
+            }
+            virtual bool takesArg() const { return !IsBool<M>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+            M C::* member;
+        };
+        template<typename C, typename M>
+        struct BoundUnaryMethod : IArgFunction<C>{
+            BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                typename RemoveConstRef<M>::type value;
+                convertInto( stringValue, value );
+                (p.*member)( value );
+            }
+            virtual bool takesArg() const { return !IsBool<M>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+            void (C::*member)( M );
+        };
+        template<typename C>
+        struct BoundNullaryMethod : IArgFunction<C>{
+            BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                bool value;
+                convertInto( stringValue, value );
+                if( value )
+                    (p.*member)();
+            }
+            virtual bool takesArg() const { return false; }
+            virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
+            void (C::*member)();
+        };
+
+        template<typename C>
+        struct BoundUnaryFunction : IArgFunction<C>{
+            BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
+            virtual void set( C& obj, std::string const& stringValue ) const {
+                bool value;
+                convertInto( stringValue, value );
+                if( value )
+                    function( obj );
+            }
+            virtual bool takesArg() const { return false; }
+            virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
+            void (*function)( C& );
+        };
+
+        template<typename C, typename T>
+        struct BoundBinaryFunction : IArgFunction<C>{
+            BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+            virtual void set( C& obj, std::string const& stringValue ) const {
+                typename RemoveConstRef<T>::type value;
+                convertInto( stringValue, value );
+                function( obj, value );
+            }
+            virtual bool takesArg() const { return !IsBool<T>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
+            void (*function)( C&, T );
+        };
+
+    } // namespace Detail
+
+    inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
+        std::vector<std::string> args( static_cast<std::size_t>( argc ) );
+        for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
+            args[i] = argv[i];
+
+        return args;
+    }
+
+    class Parser {
+        enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
+        Mode mode;
+        std::size_t from;
+        bool inQuotes;
+    public:
+
+        struct Token {
+            enum Type { Positional, ShortOpt, LongOpt };
+            Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
+            Type type;
+            std::string data;
+        };
+
+        Parser() : mode( None ), from( 0 ), inQuotes( false ){}
+
+        void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
+            const std::string doubleDash = "--";
+            for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
+                parseIntoTokens( args[i], tokens);
+        }
+
+        void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
+            for( std::size_t i = 0; i < arg.size(); ++i ) {
+                char c = arg[i];
+                if( c == '"' )
+                    inQuotes = !inQuotes;
+                mode = handleMode( i, c, arg, tokens );
+            }
+            mode = handleMode( arg.size(), '\0', arg, tokens );
+        }
+        Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+            switch( mode ) {
+                case None: return handleNone( i, c );
+                case MaybeShortOpt: return handleMaybeShortOpt( i, c );
+                case ShortOpt:
+                case LongOpt:
+                case SlashOpt: return handleOpt( i, c, arg, tokens );
+                case Positional: return handlePositional( i, c, arg, tokens );
+                default: throw std::logic_error( "Unknown mode" );
+            }
+        }
+
+        Mode handleNone( std::size_t i, char c ) {
+            if( inQuotes ) {
+                from = i;
+                return Positional;
+            }
+            switch( c ) {
+                case '-': return MaybeShortOpt;
+#ifdef CLARA_PLATFORM_WINDOWS
+                case '/': from = i+1; return SlashOpt;
+#endif
+                default: from = i; return Positional;
+            }
+        }
+        Mode handleMaybeShortOpt( std::size_t i, char c ) {
+            switch( c ) {
+                case '-': from = i+1; return LongOpt;
+                default: from = i; return ShortOpt;
+            }
+        }
+
+        Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+            if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
+                return mode;
+
+            std::string optName = arg.substr( from, i-from );
+            if( mode == ShortOpt )
+                for( std::size_t j = 0; j < optName.size(); ++j )
+                    tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
+            else if( mode == SlashOpt && optName.size() == 1 )
+                tokens.push_back( Token( Token::ShortOpt, optName ) );
+            else
+                tokens.push_back( Token( Token::LongOpt, optName ) );
+            return None;
+        }
+        Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+            if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
+                return mode;
+
+            std::string data = arg.substr( from, i-from );
+            tokens.push_back( Token( Token::Positional, data ) );
+            return None;
+        }
+    };
+
+    template<typename ConfigT>
+    struct CommonArgProperties {
+        CommonArgProperties() {}
+        CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+        Detail::BoundArgFunction<ConfigT> boundField;
+        std::string description;
+        std::string detail;
+        std::string placeholder; // Only value if boundField takes an arg
+
+        bool takesArg() const {
+            return !placeholder.empty();
+        }
+        void validate() const {
+            if( !boundField.isSet() )
+                throw std::logic_error( "option not bound" );
+        }
+    };
+    struct OptionArgProperties {
+        std::vector<std::string> shortNames;
+        std::string longName;
+
+        bool hasShortName( std::string const& shortName ) const {
+            return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
+        }
+        bool hasLongName( std::string const& _longName ) const {
+            return _longName == longName;
+        }
+    };
+    struct PositionalArgProperties {
+        PositionalArgProperties() : position( -1 ) {}
+        int position; // -1 means non-positional (floating)
+
+        bool isFixedPositional() const {
+            return position != -1;
+        }
+    };
+
+    template<typename ConfigT>
+    class CommandLine {
+
+        struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+            Arg() {}
+            Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+            using CommonArgProperties<ConfigT>::placeholder; // !TBD
+
+            std::string dbgName() const {
+                if( !longName.empty() )
+                    return "--" + longName;
+                if( !shortNames.empty() )
+                    return "-" + shortNames[0];
+                return "positional args";
+            }
+            std::string commands() const {
+                std::ostringstream oss;
+                bool first = true;
+                std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
+                for(; it != itEnd; ++it ) {
+                    if( first )
+                        first = false;
+                    else
+                        oss << ", ";
+                    oss << "-" << *it;
+                }
+                if( !longName.empty() ) {
+                    if( !first )
+                        oss << ", ";
+                    oss << "--" << longName;
+                }
+                if( !placeholder.empty() )
+                    oss << " <" << placeholder << ">";
+                return oss.str();
+            }
+        };
+
+        typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
+
+        friend void addOptName( Arg& arg, std::string const& optName )
+        {
+            if( optName.empty() )
+                return;
+            if( Detail::startsWith( optName, "--" ) ) {
+                if( !arg.longName.empty() )
+                    throw std::logic_error( "Only one long opt may be specified. '"
+                        + arg.longName
+                        + "' already specified, now attempting to add '"
+                        + optName + "'" );
+                arg.longName = optName.substr( 2 );
+            }
+            else if( Detail::startsWith( optName, "-" ) )
+                arg.shortNames.push_back( optName.substr( 1 ) );
+            else
+                throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
+        }
+        friend void setPositionalArg( Arg& arg, int position )
+        {
+            arg.position = position;
+        }
+
+        class ArgBuilder {
+        public:
+            ArgBuilder( Arg* arg ) : m_arg( arg ) {}
+
+            // Bind a non-boolean data member (requires placeholder string)
+            template<typename C, typename M>
+            void bind( M C::* field, std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+                m_arg->placeholder = placeholder;
+            }
+            // Bind a boolean data member (no placeholder required)
+            template<typename C>
+            void bind( bool C::* field ) {
+                m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+            }
+
+            // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+            template<typename C, typename M>
+            void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+                m_arg->placeholder = placeholder;
+            }
+
+            // Bind a method taking a single, boolean argument (no placeholder string required)
+            template<typename C>
+            void bind( void (C::* unaryMethod)( bool ) ) {
+                m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+            }
+
+            // Bind a method that takes no arguments (will be called if opt is present)
+            template<typename C>
+            void bind( void (C::* nullaryMethod)() ) {
+                m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+            }
+
+            // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+            template<typename C>
+            void bind( void (* unaryFunction)( C& ) ) {
+                m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+            }
+
+            // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+            template<typename C, typename T>
+            void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
+                m_arg->placeholder = placeholder;
+            }
+
+            ArgBuilder& describe( std::string const& description ) {
+                m_arg->description = description;
+                return *this;
+            }
+            ArgBuilder& detail( std::string const& detail ) {
+                m_arg->detail = detail;
+                return *this;
+            }
+
+        protected:
+            Arg* m_arg;
+        };
+
+        class OptBuilder : public ArgBuilder {
+        public:
+            OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
+            OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
+
+            OptBuilder& operator[]( std::string const& optName ) {
+                addOptName( *ArgBuilder::m_arg, optName );
+                return *this;
+            }
+        };
+
+    public:
+
+        CommandLine()
+        :   m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
+            m_highestSpecifiedArgPosition( 0 ),
+            m_throwOnUnrecognisedTokens( false )
+        {}
+        CommandLine( CommandLine const& other )
+        :   m_boundProcessName( other.m_boundProcessName ),
+            m_options ( other.m_options ),
+            m_positionalArgs( other.m_positionalArgs ),
+            m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
+            m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
+        {
+            if( other.m_floatingArg.get() )
+                m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
+        }
+
+        CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
+            m_throwOnUnrecognisedTokens = shouldThrow;
+            return *this;
+        }
+
+        OptBuilder operator[]( std::string const& optName ) {
+            m_options.push_back( Arg() );
+            addOptName( m_options.back(), optName );
+            OptBuilder builder( &m_options.back() );
+            return builder;
+        }
+
+        ArgBuilder operator[]( int position ) {
+            m_positionalArgs.insert( std::make_pair( position, Arg() ) );
+            if( position > m_highestSpecifiedArgPosition )
+                m_highestSpecifiedArgPosition = position;
+            setPositionalArg( m_positionalArgs[position], position );
+            ArgBuilder builder( &m_positionalArgs[position] );
+            return builder;
+        }
+
+        // Invoke this with the _ instance
+        ArgBuilder operator[]( UnpositionalTag ) {
+            if( m_floatingArg.get() )
+                throw std::logic_error( "Only one unpositional argument can be added" );
+            m_floatingArg.reset( new Arg() );
+            ArgBuilder builder( m_floatingArg.get() );
+            return builder;
+        }
+
+        template<typename C, typename M>
+        void bindProcessName( M C::* field ) {
+            m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+        }
+        template<typename C, typename M>
+        void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+            m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+        }
+
+        void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+            typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
+            std::size_t maxWidth = 0;
+            for( it = itBegin; it != itEnd; ++it )
+                maxWidth = (std::max)( maxWidth, it->commands().size() );
+
+            for( it = itBegin; it != itEnd; ++it ) {
+                Detail::Text usage( it->commands(), Detail::TextAttributes()
+                                                        .setWidth( maxWidth+indent )
+                                                        .setIndent( indent ) );
+                Detail::Text desc( it->description, Detail::TextAttributes()
+                                                        .setWidth( width - maxWidth - 3 ) );
+
+                for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
+                    std::string usageCol = i < usage.size() ? usage[i] : "";
+                    os << usageCol;
+
+                    if( i < desc.size() && !desc[i].empty() )
+                        os  << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
+                            << desc[i];
+                    os << "\n";
+                }
+            }
+        }
+        std::string optUsage() const {
+            std::ostringstream oss;
+            optUsage( oss );
+            return oss.str();
+        }
+
+        void argSynopsis( std::ostream& os ) const {
+            for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
+                if( i > 1 )
+                    os << " ";
+                typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
+                if( it != m_positionalArgs.end() )
+                    os << "<" << it->second.placeholder << ">";
+                else if( m_floatingArg.get() )
+                    os << "<" << m_floatingArg->placeholder << ">";
+                else
+                    throw std::logic_error( "non consecutive positional arguments with no floating args" );
+            }
+            // !TBD No indication of mandatory args
+            if( m_floatingArg.get() ) {
+                if( m_highestSpecifiedArgPosition > 1 )
+                    os << " ";
+                os << "[<" << m_floatingArg->placeholder << "> ...]";
+            }
+        }
+        std::string argSynopsis() const {
+            std::ostringstream oss;
+            argSynopsis( oss );
+            return oss.str();
+        }
+
+        void usage( std::ostream& os, std::string const& procName ) const {
+            validate();
+            os << "usage:\n  " << procName << " ";
+            argSynopsis( os );
+            if( !m_options.empty() ) {
+                os << " [options]\n\nwhere options are: \n";
+                optUsage( os, 2 );
+            }
+            os << "\n";
+        }
+        std::string usage( std::string const& procName ) const {
+            std::ostringstream oss;
+            usage( oss, procName );
+            return oss.str();
+        }
+
+        ConfigT parse( std::vector<std::string> const& args ) const {
+            ConfigT config;
+            parseInto( args, config );
+            return config;
+        }
+
+        std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
+            std::string processName = args.empty() ? std::string() : args[0];
+            std::size_t lastSlash = processName.find_last_of( "/\\" );
+            if( lastSlash != std::string::npos )
+                processName = processName.substr( lastSlash+1 );
+            m_boundProcessName.set( config, processName );
+            std::vector<Parser::Token> tokens;
+            Parser parser;
+            parser.parseIntoTokens( args, tokens );
+            return populate( tokens, config );
+        }
+
+        std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            validate();
+            std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+            unusedTokens = populateFixedArgs( unusedTokens, config );
+            unusedTokens = populateFloatingArgs( unusedTokens, config );
+            return unusedTokens;
+        }
+
+        std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            std::vector<Parser::Token> unusedTokens;
+            std::vector<std::string> errors;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
+                for(; it != itEnd; ++it ) {
+                    Arg const& arg = *it;
+
+                    try {
+                        if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
+                            ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
+                            if( arg.takesArg() ) {
+                                if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
+                                    errors.push_back( "Expected argument to option: " + token.data );
+                                else
+                                    arg.boundField.set( config, tokens[++i].data );
+                            }
+                            else {
+                                arg.boundField.set( config, "true" );
+                            }
+                            break;
+                        }
+                    }
+                    catch( std::exception& ex ) {
+                        errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
+                    }
+                }
+                if( it == itEnd ) {
+                    if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
+                        unusedTokens.push_back( token );
+                    else if( errors.empty() && m_throwOnUnrecognisedTokens )
+                        errors.push_back( "unrecognised option: " + token.data );
+                }
+            }
+            if( !errors.empty() ) {
+                std::ostringstream oss;
+                for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
+                        it != itEnd;
+                        ++it ) {
+                    if( it != errors.begin() )
+                        oss << "\n";
+                    oss << *it;
+                }
+                throw std::runtime_error( oss.str() );
+            }
+            return unusedTokens;
+        }
+        std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            std::vector<Parser::Token> unusedTokens;
+            int position = 1;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
+                if( it != m_positionalArgs.end() )
+                    it->second.boundField.set( config, token.data );
+                else
+                    unusedTokens.push_back( token );
+                if( token.type == Parser::Token::Positional )
+                    position++;
+            }
+            return unusedTokens;
+        }
+        std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            if( !m_floatingArg.get() )
+                return tokens;
+            std::vector<Parser::Token> unusedTokens;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                if( token.type == Parser::Token::Positional )
+                    m_floatingArg->boundField.set( config, token.data );
+                else
+                    unusedTokens.push_back( token );
+            }
+            return unusedTokens;
+        }
+
+        void validate() const
+        {
+            if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
+                throw std::logic_error( "No options or arguments specified" );
+
+            for( typename std::vector<Arg>::const_iterator  it = m_options.begin(),
+                                                            itEnd = m_options.end();
+                    it != itEnd; ++it )
+                it->validate();
+        }
+
+    private:
+        Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+        std::vector<Arg> m_options;
+        std::map<int, Arg> m_positionalArgs;
+        ArgAutoPtr m_floatingArg;
+        int m_highestSpecifiedArgPosition;
+        bool m_throwOnUnrecognisedTokens;
+    };
+
+} // end namespace Clara
+
+STITCH_CLARA_CLOSE_NAMESPACE
+#undef STITCH_CLARA_OPEN_NAMESPACE
+#undef STITCH_CLARA_CLOSE_NAMESPACE
+
+#endif // TWOBLUECUBES_CLARA_H_INCLUDED
+#undef STITCH_CLARA_OPEN_NAMESPACE
+
+// Restore Clara's value for console width, if present
+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
+#include <fstream>
+#include <ctime>
+
+namespace Catch {
+
+    inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
+    inline void abortAfterX( ConfigData& config, int x ) {
+        if( x < 1 )
+            throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
+        config.abortAfter = x;
+    }
+    inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
+    inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
+    inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
+
+    inline void addWarning( ConfigData& config, std::string const& _warning ) {
+        if( _warning == "NoAssertions" )
+            config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
+        else
+            throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
+    }
+    inline void setOrder( ConfigData& config, std::string const& order ) {
+        if( startsWith( "declared", order ) )
+            config.runOrder = RunTests::InDeclarationOrder;
+        else if( startsWith( "lexical", order ) )
+            config.runOrder = RunTests::InLexicographicalOrder;
+        else if( startsWith( "random", order ) )
+            config.runOrder = RunTests::InRandomOrder;
+        else
+            throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
+    }
+    inline void setRngSeed( ConfigData& config, std::string const& seed ) {
+        if( seed == "time" ) {
+            config.rngSeed = static_cast<unsigned int>( std::time(0) );
+        }
+        else {
+            std::stringstream ss;
+            ss << seed;
+            ss >> config.rngSeed;
+            if( ss.fail() )
+                throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
+        }
+    }
+    inline void setVerbosity( ConfigData& config, int level ) {
+        // !TBD: accept strings?
+        config.verbosity = static_cast<Verbosity::Level>( level );
+    }
+    inline void setShowDurations( ConfigData& config, bool _showDurations ) {
+        config.showDurations = _showDurations
+            ? ShowDurations::Always
+            : ShowDurations::Never;
+    }
+    inline void setUseColour( ConfigData& config, std::string const& value ) {
+        std::string mode = toLower( value );
+
+        if( mode == "yes" )
+            config.useColour = UseColour::Yes;
+        else if( mode == "no" )
+            config.useColour = UseColour::No;
+        else if( mode == "auto" )
+            config.useColour = UseColour::Auto;
+        else
+            throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
+    }
+    inline void forceColour( ConfigData& config ) {
+        config.useColour = UseColour::Yes;
+    }
+    inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
+        std::ifstream f( _filename.c_str() );
+        if( !f.is_open() )
+            throw std::domain_error( "Unable to load input file: " + _filename );
+
+        std::string line;
+        while( std::getline( f, line ) ) {
+            line = trim(line);
+            if( !line.empty() && !startsWith( line, '#' ) ) {
+                if( !startsWith( line, '"' ) )
+                    line = '"' + line + '"';
+                addTestOrTags( config, line + ',' );
+            }
+        }
+    }
+
+    inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
+
+        using namespace Clara;
+        CommandLine<ConfigData> cli;
+
+        cli.bindProcessName( &ConfigData::processName );
+
+        cli["-?"]["-h"]["--help"]
+            .describe( "display usage information" )
+            .bind( &ConfigData::showHelp );
+
+        cli["-l"]["--list-tests"]
+            .describe( "list all/matching test cases" )
+            .bind( &ConfigData::listTests );
+
+        cli["-t"]["--list-tags"]
+            .describe( "list all/matching tags" )
+            .bind( &ConfigData::listTags );
+
+        cli["-s"]["--success"]
+            .describe( "include successful tests in output" )
+            .bind( &ConfigData::showSuccessfulTests );
+
+        cli["-b"]["--break"]
+            .describe( "break into debugger on failure" )
+            .bind( &ConfigData::shouldDebugBreak );
+
+        cli["-e"]["--nothrow"]
+            .describe( "skip exception tests" )
+            .bind( &ConfigData::noThrow );
+
+        cli["-i"]["--invisibles"]
+            .describe( "show invisibles (tabs, newlines)" )
+            .bind( &ConfigData::showInvisibles );
+
+        cli["-o"]["--out"]
+            .describe( "output filename" )
+            .bind( &ConfigData::outputFilename, "filename" );
+
+        cli["-r"]["--reporter"]
+//            .placeholder( "name[:filename]" )
+            .describe( "reporter to use (defaults to console)" )
+            .bind( &addReporterName, "name" );
+
+        cli["-n"]["--name"]
+            .describe( "suite name" )
+            .bind( &ConfigData::name, "name" );
+
+        cli["-a"]["--abort"]
+            .describe( "abort at first failure" )
+            .bind( &abortAfterFirst );
+
+        cli["-x"]["--abortx"]
+            .describe( "abort after x failures" )
+            .bind( &abortAfterX, "no. failures" );
+
+        cli["-w"]["--warn"]
+            .describe( "enable warnings" )
+            .bind( &addWarning, "warning name" );
+
+// - needs updating if reinstated
+//        cli.into( &setVerbosity )
+//            .describe( "level of verbosity (0=no output)" )
+//            .shortOpt( "v")
+//            .longOpt( "verbosity" )
+//            .placeholder( "level" );
+
+        cli[_]
+            .describe( "which test or tests to use" )
+            .bind( &addTestOrTags, "test name, pattern or tags" );
+
+        cli["-d"]["--durations"]
+            .describe( "show test durations" )
+            .bind( &setShowDurations, "yes|no" );
+
+        cli["-f"]["--input-file"]
+            .describe( "load test names to run from a file" )
+            .bind( &loadTestNamesFromFile, "filename" );
+
+        cli["-#"]["--filenames-as-tags"]
+            .describe( "adds a tag for the filename" )
+            .bind( &ConfigData::filenamesAsTags );
+
+        cli["-c"]["--section"]
+                .describe( "specify section to run" )
+                .bind( &addSectionToRun, "section name" );
+
+        // Less common commands which don't have a short form
+        cli["--list-test-names-only"]
+            .describe( "list all/matching test cases names only" )
+            .bind( &ConfigData::listTestNamesOnly );
+
+        cli["--list-reporters"]
+            .describe( "list all reporters" )
+            .bind( &ConfigData::listReporters );
+
+        cli["--order"]
+            .describe( "test case order (defaults to decl)" )
+            .bind( &setOrder, "decl|lex|rand" );
+
+        cli["--rng-seed"]
+            .describe( "set a specific seed for random numbers" )
+            .bind( &setRngSeed, "'time'|number" );
+
+        cli["--force-colour"]
+            .describe( "force colourised output (deprecated)" )
+            .bind( &forceColour );
+
+        cli["--use-colour"]
+            .describe( "should output be colourised" )
+            .bind( &setUseColour, "yes|no" );
+
+        return cli;
+    }
+
+} // end namespace Catch
+
+// #included from: internal/catch_list.hpp
+#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+
+// #included from: catch_text.h
+#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
+
+#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
+// #included from: ../external/tbc_text_format.h
+// Only use header guard if we are not using an outer namespace
+#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+#  ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#   define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#  endif
+# else
+#  define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# endif
+#endif
+#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+    struct TextAttributes {
+        TextAttributes()
+        :   initialIndent( std::string::npos ),
+            indent( 0 ),
+            width( consoleWidth-1 )
+        {}
+
+        TextAttributes& setInitialIndent( std::size_t _value )  { initialIndent = _value; return *this; }
+        TextAttributes& setIndent( std::size_t _value )         { indent = _value; return *this; }
+        TextAttributes& setWidth( std::size_t _value )          { width = _value; return *this; }
+
+        std::size_t initialIndent;  // indent of first line, or npos
+        std::size_t indent;         // indent of subsequent lines, or all if initialIndent is npos
+        std::size_t width;          // maximum width of text, including indent. Longer text will wrap
+    };
+
+    class Text {
+    public:
+        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+        : attr( _attr )
+        {
+            const std::string wrappableBeforeChars = "[({<\t";
+            const std::string wrappableAfterChars = "])}>-,./|\\";
+            const std::string wrappableInsteadOfChars = " \n\r";
+            std::string indent = _attr.initialIndent != std::string::npos
+                ? std::string( _attr.initialIndent, ' ' )
+                : std::string( _attr.indent, ' ' );
+
+            typedef std::string::const_iterator iterator;
+            iterator it = _str.begin();
+            const iterator strEnd = _str.end();
+
+            while( it != strEnd ) {
+
+                if( lines.size() >= 1000 ) {
+                    lines.push_back( "... message truncated due to excessive size" );
+                    return;
+                }
+
+                std::string suffix;
+                std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
+                iterator itEnd = it+width;
+                iterator itNext = _str.end();
+
+                iterator itNewLine = std::find( it, itEnd, '\n' );
+                if( itNewLine != itEnd )
+                    itEnd = itNewLine;
+
+                if( itEnd != strEnd  ) {
+                    bool foundWrapPoint = false;
+                    iterator findIt = itEnd;
+                    do {
+                        if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
+                            itEnd = findIt+1;
+                            itNext = findIt+1;
+                            foundWrapPoint = true;
+                        }
+                        else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
+                            itEnd = findIt;
+                            itNext = findIt;
+                            foundWrapPoint = true;
+                        }
+                        else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
+                            itNext = findIt+1;
+                            itEnd = findIt;
+                            foundWrapPoint = true;
+                        }
+                        if( findIt == it )
+                            break;
+                        else
+                            --findIt;
+                    }
+                    while( !foundWrapPoint );
+
+                    if( !foundWrapPoint ) {
+                        // No good wrap char, so we'll break mid word and add a hyphen
+                        --itEnd;
+                        itNext = itEnd;
+                        suffix = "-";
+                    }
+                    else {
+                        while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
+                            --itEnd;
+                    }
+                }
+                lines.push_back( indent + std::string( it, itEnd ) + suffix );
+
+                if( indent.size() != _attr.indent )
+                    indent = std::string( _attr.indent, ' ' );
+                it = itNext;
+            }
+        }
+
+        typedef std::vector<std::string>::const_iterator const_iterator;
+
+        const_iterator begin() const { return lines.begin(); }
+        const_iterator end() const { return lines.end(); }
+        std::string const& last() const { return lines.back(); }
+        std::size_t size() const { return lines.size(); }
+        std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << *this;
+            return oss.str();
+        }
+
+        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+            for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+                it != itEnd; ++it ) {
+                if( it != _text.begin() )
+                    _stream << "\n";
+                _stream << *it;
+            }
+            return _stream;
+        }
+
+    private:
+        std::string str;
+        TextAttributes attr;
+        std::vector<std::string> lines;
+    };
+
+} // end namespace Tbc
+
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+
+namespace Catch {
+    using Tbc::Text;
+    using Tbc::TextAttributes;
+}
+
+// #included from: catch_console_colour.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
+
+namespace Catch {
+
+    struct Colour {
+        enum Code {
+            None = 0,
+
+            White,
+            Red,
+            Green,
+            Blue,
+            Cyan,
+            Yellow,
+            Grey,
+
+            Bright = 0x10,
+
+            BrightRed = Bright | Red,
+            BrightGreen = Bright | Green,
+            LightGrey = Bright | Grey,
+            BrightWhite = Bright | White,
+
+            // By intention
+            FileName = LightGrey,
+            Warning = Yellow,
+            ResultError = BrightRed,
+            ResultSuccess = BrightGreen,
+            ResultExpectedFailure = Warning,
+
+            Error = BrightRed,
+            Success = Green,
+
+            OriginalExpression = Cyan,
+            ReconstructedExpression = Yellow,
+
+            SecondaryText = LightGrey,
+            Headers = White
+        };
+
+        // Use constructed object for RAII guard
+        Colour( Code _colourCode );
+        Colour( Colour const& other );
+        ~Colour();
+
+        // Use static method for one-shot changes
+        static void use( Code _colourCode );
+
+    private:
+        bool m_moved;
+    };
+
+    inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_reporter.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
+
+#include <string>
+#include <ostream>
+#include <map>
+
+namespace Catch
+{
+    struct ReporterConfig {
+        explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
+        :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+        ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
+        :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+        std::ostream& stream() const    { return *m_stream; }
+        Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
+
+    private:
+        std::ostream* m_stream;
+        Ptr<IConfig const> m_fullConfig;
+    };
+
+    struct ReporterPreferences {
+        ReporterPreferences()
+        : shouldRedirectStdOut( false )
+        {}
+
+        bool shouldRedirectStdOut;
+    };
+
+    template<typename T>
+    struct LazyStat : Option<T> {
+        LazyStat() : used( false ) {}
+        LazyStat& operator=( T const& _value ) {
+            Option<T>::operator=( _value );
+            used = false;
+            return *this;
+        }
+        void reset() {
+            Option<T>::reset();
+            used = false;
+        }
+        bool used;
+    };
+
+    struct TestRunInfo {
+        TestRunInfo( std::string const& _name ) : name( _name ) {}
+        std::string name;
+    };
+    struct GroupInfo {
+        GroupInfo(  std::string const& _name,
+                    std::size_t _groupIndex,
+                    std::size_t _groupsCount )
+        :   name( _name ),
+            groupIndex( _groupIndex ),
+            groupsCounts( _groupsCount )
+        {}
+
+        std::string name;
+        std::size_t groupIndex;
+        std::size_t groupsCounts;
+    };
+
+    struct AssertionStats {
+        AssertionStats( AssertionResult const& _assertionResult,
+                        std::vector<MessageInfo> const& _infoMessages,
+                        Totals const& _totals )
+        :   assertionResult( _assertionResult ),
+            infoMessages( _infoMessages ),
+            totals( _totals )
+        {
+            if( assertionResult.hasMessage() ) {
+                // Copy message into messages list.
+                // !TBD This should have been done earlier, somewhere
+                MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
+                builder << assertionResult.getMessage();
+                builder.m_info.message = builder.m_stream.str();
+
+                infoMessages.push_back( builder.m_info );
+            }
+        }
+        virtual ~AssertionStats();
+
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        AssertionStats( AssertionStats const& )              = default;
+        AssertionStats( AssertionStats && )                  = default;
+        AssertionStats& operator = ( AssertionStats const& ) = default;
+        AssertionStats& operator = ( AssertionStats && )     = default;
+#  endif
+
+        AssertionResult assertionResult;
+        std::vector<MessageInfo> infoMessages;
+        Totals totals;
+    };
+
+    struct SectionStats {
+        SectionStats(   SectionInfo const& _sectionInfo,
+                        Counts const& _assertions,
+                        double _durationInSeconds,
+                        bool _missingAssertions )
+        :   sectionInfo( _sectionInfo ),
+            assertions( _assertions ),
+            durationInSeconds( _durationInSeconds ),
+            missingAssertions( _missingAssertions )
+        {}
+        virtual ~SectionStats();
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        SectionStats( SectionStats const& )              = default;
+        SectionStats( SectionStats && )                  = default;
+        SectionStats& operator = ( SectionStats const& ) = default;
+        SectionStats& operator = ( SectionStats && )     = default;
+#  endif
+
+        SectionInfo sectionInfo;
+        Counts assertions;
+        double durationInSeconds;
+        bool missingAssertions;
+    };
+
+    struct TestCaseStats {
+        TestCaseStats(  TestCaseInfo const& _testInfo,
+                        Totals const& _totals,
+                        std::string const& _stdOut,
+                        std::string const& _stdErr,
+                        bool _aborting )
+        : testInfo( _testInfo ),
+            totals( _totals ),
+            stdOut( _stdOut ),
+            stdErr( _stdErr ),
+            aborting( _aborting )
+        {}
+        virtual ~TestCaseStats();
+
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        TestCaseStats( TestCaseStats const& )              = default;
+        TestCaseStats( TestCaseStats && )                  = default;
+        TestCaseStats& operator = ( TestCaseStats const& ) = default;
+        TestCaseStats& operator = ( TestCaseStats && )     = default;
+#  endif
+
+        TestCaseInfo testInfo;
+        Totals totals;
+        std::string stdOut;
+        std::string stdErr;
+        bool aborting;
+    };
+
+    struct TestGroupStats {
+        TestGroupStats( GroupInfo const& _groupInfo,
+                        Totals const& _totals,
+                        bool _aborting )
+        :   groupInfo( _groupInfo ),
+            totals( _totals ),
+            aborting( _aborting )
+        {}
+        TestGroupStats( GroupInfo const& _groupInfo )
+        :   groupInfo( _groupInfo ),
+            aborting( false )
+        {}
+        virtual ~TestGroupStats();
+
+#  ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        TestGroupStats( TestGroupStats const& )              = default;
+        TestGroupStats( TestGroupStats && )                  = default;
+        TestGroupStats& operator = ( TestGroupStats const& ) = default;
+        TestGroupStats& operator = ( TestGroupStats && )     = default;
+#  endif
+
+        GroupInfo groupInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    struct TestRunStats {
+        TestRunStats(   TestRunInfo const& _runInfo,
+                        Totals const& _totals,
+                        bool _aborting )
+        :   runInfo( _runInfo ),
+            totals( _totals ),
+            aborting( _aborting )
+        {}
+        virtual ~TestRunStats();
+
+#  ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
+        TestRunStats( TestRunStats const& _other )
+        :   runInfo( _other.runInfo ),
+            totals( _other.totals ),
+            aborting( _other.aborting )
+        {}
+#  else
+        TestRunStats( TestRunStats const& )              = default;
+        TestRunStats( TestRunStats && )                  = default;
+        TestRunStats& operator = ( TestRunStats const& ) = default;
+        TestRunStats& operator = ( TestRunStats && )     = default;
+#  endif
+
+        TestRunInfo runInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    class MultipleReporters;
+
+    struct IStreamingReporter : IShared {
+        virtual ~IStreamingReporter();
+
+        // Implementing class must also provide the following static method:
+        // static std::string getDescription();
+
+        virtual ReporterPreferences getPreferences() const = 0;
+
+        virtual void noMatchingTestCases( std::string const& spec ) = 0;
+
+        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
+
+        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
+
+        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+
+        // The return value indicates if the messages buffer should be cleared:
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+
+        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
+        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
+
+        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
+
+        virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
+    };
+
+    struct IReporterFactory : IShared {
+        virtual ~IReporterFactory();
+        virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
+        virtual std::string getDescription() const = 0;
+    };
+
+    struct IReporterRegistry {
+        typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
+        typedef std::vector<Ptr<IReporterFactory> > Listeners;
+
+        virtual ~IReporterRegistry();
+        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
+        virtual FactoryMap const& getFactories() const = 0;
+        virtual Listeners const& getListeners() const = 0;
+    };
+
+    Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
+
+}
+
+#include <limits>
+#include <algorithm>
+
+namespace Catch {
+
+    inline std::size_t listTests( Config const& config ) {
+
+        TestSpec testSpec = config.testSpec();
+        if( config.testSpec().hasFilters() )
+            Catch::cout() << "Matching test cases:\n";
+        else {
+            Catch::cout() << "All available test cases:\n";
+            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+        }
+
+        std::size_t matchedTests = 0;
+        TextAttributes nameAttr, tagsAttr;
+        nameAttr.setInitialIndent( 2 ).setIndent( 4 );
+        tagsAttr.setIndent( 6 );
+
+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            matchedTests++;
+            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+            Colour::Code colour = testCaseInfo.isHidden()
+                ? Colour::SecondaryText
+                : Colour::None;
+            Colour colourGuard( colour );
+
+            Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
+            if( !testCaseInfo.tags.empty() )
+                Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
+        }
+
+        if( !config.testSpec().hasFilters() )
+            Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
+        else
+            Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
+        return matchedTests;
+    }
+
+    inline std::size_t listTestsNamesOnly( Config const& config ) {
+        TestSpec testSpec = config.testSpec();
+        if( !config.testSpec().hasFilters() )
+            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+        std::size_t matchedTests = 0;
+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            matchedTests++;
+            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+            if( startsWith( testCaseInfo.name, '#' ) )
+               Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
+            else
+               Catch::cout() << testCaseInfo.name << std::endl;
+        }
+        return matchedTests;
+    }
+
+    struct TagInfo {
+        TagInfo() : count ( 0 ) {}
+        void add( std::string const& spelling ) {
+            ++count;
+            spellings.insert( spelling );
+        }
+        std::string all() const {
+            std::string out;
+            for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
+                        it != itEnd;
+                        ++it )
+                out += "[" + *it + "]";
+            return out;
+        }
+        std::set<std::string> spellings;
+        std::size_t count;
+    };
+
+    inline std::size_t listTags( Config const& config ) {
+        TestSpec testSpec = config.testSpec();
+        if( config.testSpec().hasFilters() )
+            Catch::cout() << "Tags for matching test cases:\n";
+        else {
+            Catch::cout() << "All available tags:\n";
+            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+        }
+
+        std::map<std::string, TagInfo> tagCounts;
+
+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(),
+                                                        tagItEnd = it->getTestCaseInfo().tags.end();
+                    tagIt != tagItEnd;
+                    ++tagIt ) {
+                std::string tagName = *tagIt;
+                std::string lcaseTagName = toLower( tagName );
+                std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
+                if( countIt == tagCounts.end() )
+                    countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
+                countIt->second.add( tagName );
+            }
+        }
+
+        for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
+                                                            countItEnd = tagCounts.end();
+                countIt != countItEnd;
+                ++countIt ) {
+            std::ostringstream oss;
+            oss << "  " << std::setw(2) << countIt->second.count << "  ";
+            Text wrapper( countIt->second.all(), TextAttributes()
+                                                    .setInitialIndent( 0 )
+                                                    .setIndent( oss.str().size() )
+                                                    .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
+            Catch::cout() << oss.str() << wrapper << '\n';
+        }
+        Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
+        return tagCounts.size();
+    }
+
+    inline std::size_t listReporters( Config const& /*config*/ ) {
+        Catch::cout() << "Available reporters:\n";
+        IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+        IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
+        std::size_t maxNameLen = 0;
+        for(it = itBegin; it != itEnd; ++it )
+            maxNameLen = (std::max)( maxNameLen, it->first.size() );
+
+        for(it = itBegin; it != itEnd; ++it ) {
+            Text wrapper( it->second->getDescription(), TextAttributes()
+                                                        .setInitialIndent( 0 )
+                                                        .setIndent( 7+maxNameLen )
+                                                        .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
+            Catch::cout() << "  "
+                    << it->first
+                    << ':'
+                    << std::string( maxNameLen - it->first.size() + 2, ' ' )
+                    << wrapper << '\n';
+        }
+        Catch::cout() << std::endl;
+        return factories.size();
+    }
+
+    inline Option<std::size_t> list( Config const& config ) {
+        Option<std::size_t> listedCount;
+        if( config.listTests() )
+            listedCount = listedCount.valueOr(0) + listTests( config );
+        if( config.listTestNamesOnly() )
+            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
+        if( config.listTags() )
+            listedCount = listedCount.valueOr(0) + listTags( config );
+        if( config.listReporters() )
+            listedCount = listedCount.valueOr(0) + listReporters( config );
+        return listedCount;
+    }
+
+} // end namespace Catch
+
+// #included from: internal/catch_run_context.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
+
+// #included from: catch_test_case_tracker.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
+
+#include <algorithm>
+#include <string>
+#include <assert.h>
+#include <vector>
+#include <stdexcept>
+
+CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
+
+namespace Catch {
+namespace TestCaseTracking {
+
+    struct NameAndLocation {
+        std::string name;
+        SourceLineInfo location;
+
+        NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
+        :   name( _name ),
+            location( _location )
+        {}
+    };
+
+    struct ITracker : SharedImpl<> {
+        virtual ~ITracker();
+
+        // static queries
+        virtual NameAndLocation const& nameAndLocation() const = 0;
+
+        // dynamic queries
+        virtual bool isComplete() const = 0; // Successfully completed or failed
+        virtual bool isSuccessfullyCompleted() const = 0;
+        virtual bool isOpen() const = 0; // Started but not complete
+        virtual bool hasChildren() const = 0;
+
+        virtual ITracker& parent() = 0;
+
+        // actions
+        virtual void close() = 0; // Successfully complete
+        virtual void fail() = 0;
+        virtual void markAsNeedingAnotherRun() = 0;
+
+        virtual void addChild( Ptr<ITracker> const& child ) = 0;
+        virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
+        virtual void openChild() = 0;
+
+        // Debug/ checking
+        virtual bool isSectionTracker() const = 0;
+        virtual bool isIndexTracker() const = 0;
+    };
+
+    class  TrackerContext {
+
+        enum RunState {
+            NotStarted,
+            Executing,
+            CompletedCycle
+        };
+
+        Ptr<ITracker> m_rootTracker;
+        ITracker* m_currentTracker;
+        RunState m_runState;
+
+    public:
+
+        static TrackerContext& instance() {
+            static TrackerContext s_instance;
+            return s_instance;
+        }
+
+        TrackerContext()
+        :   m_currentTracker( CATCH_NULL ),
+            m_runState( NotStarted )
+        {}
+
+        ITracker& startRun();
+
+        void endRun() {
+            m_rootTracker.reset();
+            m_currentTracker = CATCH_NULL;
+            m_runState = NotStarted;
+        }
+
+        void startCycle() {
+            m_currentTracker = m_rootTracker.get();
+            m_runState = Executing;
+        }
+        void completeCycle() {
+            m_runState = CompletedCycle;
+        }
+
+        bool completedCycle() const {
+            return m_runState == CompletedCycle;
+        }
+        ITracker& currentTracker() {
+            return *m_currentTracker;
+        }
+        void setCurrentTracker( ITracker* tracker ) {
+            m_currentTracker = tracker;
+        }
+    };
+
+    class TrackerBase : public ITracker {
+    protected:
+        enum CycleState {
+            NotStarted,
+            Executing,
+            ExecutingChildren,
+            NeedsAnotherRun,
+            CompletedSuccessfully,
+            Failed
+        };
+        class TrackerHasName {
+            NameAndLocation m_nameAndLocation;
+        public:
+            TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
+            bool operator ()( Ptr<ITracker> const& tracker ) {
+                return
+                    tracker->nameAndLocation().name == m_nameAndLocation.name &&
+                    tracker->nameAndLocation().location == m_nameAndLocation.location;
+            }
+        };
+        typedef std::vector<Ptr<ITracker> > Children;
+        NameAndLocation m_nameAndLocation;
+        TrackerContext& m_ctx;
+        ITracker* m_parent;
+        Children m_children;
+        CycleState m_runState;
+    public:
+        TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+        :   m_nameAndLocation( nameAndLocation ),
+            m_ctx( ctx ),
+            m_parent( parent ),
+            m_runState( NotStarted )
+        {}
+        virtual ~TrackerBase();
+
+        virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
+            return m_nameAndLocation;
+        }
+        virtual bool isComplete() const CATCH_OVERRIDE {
+            return m_runState == CompletedSuccessfully || m_runState == Failed;
+        }
+        virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
+            return m_runState == CompletedSuccessfully;
+        }
+        virtual bool isOpen() const CATCH_OVERRIDE {
+            return m_runState != NotStarted && !isComplete();
+        }
+        virtual bool hasChildren() const CATCH_OVERRIDE {
+            return !m_children.empty();
+        }
+
+        virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
+            m_children.push_back( child );
+        }
+
+        virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
+            Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
+            return( it != m_children.end() )
+                ? it->get()
+                : CATCH_NULL;
+        }
+        virtual ITracker& parent() CATCH_OVERRIDE {
+            assert( m_parent ); // Should always be non-null except for root
+            return *m_parent;
+        }
+
+        virtual void openChild() CATCH_OVERRIDE {
+            if( m_runState != ExecutingChildren ) {
+                m_runState = ExecutingChildren;
+                if( m_parent )
+                    m_parent->openChild();
+            }
+        }
+
+        virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
+        virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
+
+        void open() {
+            m_runState = Executing;
+            moveToThis();
+            if( m_parent )
+                m_parent->openChild();
+        }
+
+        virtual void close() CATCH_OVERRIDE {
+
+            // Close any still open children (e.g. generators)
+            while( &m_ctx.currentTracker() != this )
+                m_ctx.currentTracker().close();
+
+            switch( m_runState ) {
+                case NotStarted:
+                case CompletedSuccessfully:
+                case Failed:
+                    throw std::logic_error( "Illogical state" );
+
+                case NeedsAnotherRun:
+                    break;;
+
+                case Executing:
+                    m_runState = CompletedSuccessfully;
+                    break;
+                case ExecutingChildren:
+                    if( m_children.empty() || m_children.back()->isComplete() )
+                        m_runState = CompletedSuccessfully;
+                    break;
+
+                default:
+                    throw std::logic_error( "Unexpected state" );
+            }
+            moveToParent();
+            m_ctx.completeCycle();
+        }
+        virtual void fail() CATCH_OVERRIDE {
+            m_runState = Failed;
+            if( m_parent )
+                m_parent->markAsNeedingAnotherRun();
+            moveToParent();
+            m_ctx.completeCycle();
+        }
+        virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
+            m_runState = NeedsAnotherRun;
+        }
+    private:
+        void moveToParent() {
+            assert( m_parent );
+            m_ctx.setCurrentTracker( m_parent );
+        }
+        void moveToThis() {
+            m_ctx.setCurrentTracker( this );
+        }
+    };
+
+    class SectionTracker : public TrackerBase {
+        std::vector<std::string> m_filters;
+    public:
+        SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+        :   TrackerBase( nameAndLocation, ctx, parent )
+        {
+            if( parent ) {
+                while( !parent->isSectionTracker() )
+                    parent = &parent->parent();
+
+                SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
+                addNextFilters( parentSection.m_filters );
+            }
+        }
+        virtual ~SectionTracker();
+
+        virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
+
+        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
+            SectionTracker* section = CATCH_NULL;
+
+            ITracker& currentTracker = ctx.currentTracker();
+            if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
+                assert( childTracker );
+                assert( childTracker->isSectionTracker() );
+                section = static_cast<SectionTracker*>( childTracker );
+            }
+            else {
+                section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
+                currentTracker.addChild( section );
+            }
+            if( !ctx.completedCycle() )
+                section->tryOpen();
+            return *section;
+        }
+
+        void tryOpen() {
+            if( !isComplete() && (m_filters.empty() || m_filters[0].empty() ||  m_filters[0] == m_nameAndLocation.name ) )
+                open();
+        }
+
+        void addInitialFilters( std::vector<std::string> const& filters ) {
+            if( !filters.empty() ) {
+                m_filters.push_back(""); // Root - should never be consulted
+                m_filters.push_back(""); // Test Case - not a section filter
+                m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
+            }
+        }
+        void addNextFilters( std::vector<std::string> const& filters ) {
+            if( filters.size() > 1 )
+                m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
+        }
+    };
+
+    class IndexTracker : public TrackerBase {
+        int m_size;
+        int m_index;
+    public:
+        IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
+        :   TrackerBase( nameAndLocation, ctx, parent ),
+            m_size( size ),
+            m_index( -1 )
+        {}
+        virtual ~IndexTracker();
+
+        virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
+
+        static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
+            IndexTracker* tracker = CATCH_NULL;
+
+            ITracker& currentTracker = ctx.currentTracker();
+            if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
+                assert( childTracker );
+                assert( childTracker->isIndexTracker() );
+                tracker = static_cast<IndexTracker*>( childTracker );
+            }
+            else {
+                tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
+                currentTracker.addChild( tracker );
+            }
+
+            if( !ctx.completedCycle() && !tracker->isComplete() ) {
+                if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
+                    tracker->moveNext();
+                tracker->open();
+            }
+
+            return *tracker;
+        }
+
+        int index() const { return m_index; }
+
+        void moveNext() {
+            m_index++;
+            m_children.clear();
+        }
+
+        virtual void close() CATCH_OVERRIDE {
+            TrackerBase::close();
+            if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
+                m_runState = Executing;
+        }
+    };
+
+    inline ITracker& TrackerContext::startRun() {
+        m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
+        m_currentTracker = CATCH_NULL;
+        m_runState = Executing;
+        return *m_rootTracker;
+    }
+
+} // namespace TestCaseTracking
+
+using TestCaseTracking::ITracker;
+using TestCaseTracking::TrackerContext;
+using TestCaseTracking::SectionTracker;
+using TestCaseTracking::IndexTracker;
+
+} // namespace Catch
+
+CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
+
+// #included from: catch_fatal_condition.hpp
+#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
+
+namespace Catch {
+
+    // Report the error condition
+    inline void reportFatal( std::string const& message ) {
+        IContext& context = Catch::getCurrentContext();
+        IResultCapture* resultCapture = context.getResultCapture();
+        resultCapture->handleFatalErrorCondition( message );
+    }
+
+} // namespace Catch
+
+#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
+// #included from: catch_windows_h_proxy.h
+
+#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
+
+#ifdef CATCH_DEFINES_NOMINMAX
+#  define NOMINMAX
+#endif
+#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef CATCH_DEFINES_NOMINMAX
+#  undef NOMINMAX
+#endif
+#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+#  undef WIN32_LEAN_AND_MEAN
+#endif
+
+
+#  if !defined ( CATCH_CONFIG_WINDOWS_SEH )
+
+namespace Catch {
+    struct FatalConditionHandler {
+        void reset() {}
+    };
+}
+
+#  else // CATCH_CONFIG_WINDOWS_SEH is defined
+
+namespace Catch {
+
+    struct SignalDefs { DWORD id; const char* name; };
+    extern SignalDefs signalDefs[];
+    // There is no 1-1 mapping between signals and windows exceptions.
+    // Windows can easily distinguish between SO and SigSegV,
+    // but SigInt, SigTerm, etc are handled differently.
+    SignalDefs signalDefs[] = {
+        { EXCEPTION_ILLEGAL_INSTRUCTION,  "SIGILL - Illegal instruction signal" },
+        { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
+        { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
+        { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
+    };
+
+    struct FatalConditionHandler {
+
+        static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
+            for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
+                if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
+                    reportFatal(signalDefs[i].name);
+                }
+            }
+            // If its not an exception we care about, pass it along.
+            // This stops us from eating debugger breaks etc.
+            return EXCEPTION_CONTINUE_SEARCH;
+        }
+
+        FatalConditionHandler() {
+            isSet = true;
+            // 32k seems enough for Catch to handle stack overflow,
+            // but the value was found experimentally, so there is no strong guarantee
+            guaranteeSize = 32 * 1024;
+            exceptionHandlerHandle = CATCH_NULL;
+            // Register as first handler in current chain
+            exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
+            // Pass in guarantee size to be filled
+            SetThreadStackGuarantee(&guaranteeSize);
+        }
+
+        static void reset() {
+            if (isSet) {
+                // Unregister handler and restore the old guarantee
+                RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+                SetThreadStackGuarantee(&guaranteeSize);
+                exceptionHandlerHandle = CATCH_NULL;
+                isSet = false;
+            }
+        }
+
+        ~FatalConditionHandler() {
+            reset();
+        }
+    private:
+        static bool isSet;
+        static ULONG guaranteeSize;
+        static PVOID exceptionHandlerHandle;
+    };
+
+    bool FatalConditionHandler::isSet = false;
+    ULONG FatalConditionHandler::guaranteeSize = 0;
+    PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
+
+} // namespace Catch
+
+#  endif // CATCH_CONFIG_WINDOWS_SEH
+
+#else // Not Windows - assumed to be POSIX compatible //////////////////////////
+
+#  if !defined(CATCH_CONFIG_POSIX_SIGNALS)
+
+namespace Catch {
+    struct FatalConditionHandler {
+        void reset() {}
+    };
+}
+
+#  else // CATCH_CONFIG_POSIX_SIGNALS is defined
+
+#include <signal.h>
+
+namespace Catch {
+
+    struct SignalDefs {
+        int id;
+        const char* name;
+    };
+    extern SignalDefs signalDefs[];
+    SignalDefs signalDefs[] = {
+            { SIGINT,  "SIGINT - Terminal interrupt signal" },
+            { SIGILL,  "SIGILL - Illegal instruction signal" },
+            { SIGFPE,  "SIGFPE - Floating point error signal" },
+            { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
+            { SIGTERM, "SIGTERM - Termination request signal" },
+            { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+    };
+
+    struct FatalConditionHandler {
+
+        static bool isSet;
+        static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
+        static stack_t oldSigStack;
+        static char altStackMem[SIGSTKSZ];
+
+        static void handleSignal( int sig ) {
+            std::string name = "<unknown signal>";
+            for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
+                SignalDefs &def = signalDefs[i];
+                if (sig == def.id) {
+                    name = def.name;
+                    break;
+                }
+            }
+            reset();
+            reportFatal(name);
+            raise( sig );
+        }
+
+        FatalConditionHandler() {
+            isSet = true;
+            stack_t sigStack;
+            sigStack.ss_sp = altStackMem;
+            sigStack.ss_size = SIGSTKSZ;
+            sigStack.ss_flags = 0;
+            sigaltstack(&sigStack, &oldSigStack);
+            struct sigaction sa = { 0 };
+
+            sa.sa_handler = handleSignal;
+            sa.sa_flags = SA_ONSTACK;
+            for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
+                sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
+            }
+        }
+
+        ~FatalConditionHandler() {
+            reset();
+        }
+        static void reset() {
+            if( isSet ) {
+                // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+                for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
+                    sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
+                }
+                // Return the old stack
+                sigaltstack(&oldSigStack, CATCH_NULL);
+                isSet = false;
+            }
+        }
+    };
+
+    bool FatalConditionHandler::isSet = false;
+    struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
+    stack_t FatalConditionHandler::oldSigStack = {};
+    char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
+
+} // namespace Catch
+
+#  endif // CATCH_CONFIG_POSIX_SIGNALS
+
+#endif // not Windows
+
+#include <set>
+#include <string>
+
+namespace Catch {
+
+    class StreamRedirect {
+
+    public:
+        StreamRedirect( std::ostream& stream, std::string& targetString )
+        :   m_stream( stream ),
+            m_prevBuf( stream.rdbuf() ),
+            m_targetString( targetString )
+        {
+            stream.rdbuf( m_oss.rdbuf() );
+        }
+
+        ~StreamRedirect() {
+            m_targetString += m_oss.str();
+            m_stream.rdbuf( m_prevBuf );
+        }
+
+    private:
+        std::ostream& m_stream;
+        std::streambuf* m_prevBuf;
+        std::ostringstream m_oss;
+        std::string& m_targetString;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class RunContext : public IResultCapture, public IRunner {
+
+        RunContext( RunContext const& );
+        void operator =( RunContext const& );
+
+    public:
+
+        explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
+        :   m_runInfo( _config->name() ),
+            m_context( getCurrentMutableContext() ),
+            m_activeTestCase( CATCH_NULL ),
+            m_config( _config ),
+            m_reporter( reporter ),
+            m_shouldReportUnexpected ( true )
+        {
+            m_context.setRunner( this );
+            m_context.setConfig( m_config );
+            m_context.setResultCapture( this );
+            m_reporter->testRunStarting( m_runInfo );
+        }
+
+        virtual ~RunContext() {
+            m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
+        }
+
+        void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
+            m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
+        }
+        void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
+            m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
+        }
+
+        Totals runTest( TestCase const& testCase ) {
+            Totals prevTotals = m_totals;
+
+            std::string redirectedCout;
+            std::string redirectedCerr;
+
+            TestCaseInfo testInfo = testCase.getTestCaseInfo();
+
+            m_reporter->testCaseStarting( testInfo );
+
+            m_activeTestCase = &testCase;
+
+            do {
+                ITracker& rootTracker = m_trackerContext.startRun();
+                assert( rootTracker.isSectionTracker() );
+                static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
+                do {
+                    m_trackerContext.startCycle();
+                    m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
+                    runCurrentTest( redirectedCout, redirectedCerr );
+                }
+                while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
+            }
+            // !TBD: deprecated - this will be replaced by indexed trackers
+            while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
+
+            Totals deltaTotals = m_totals.delta( prevTotals );
+            if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
+                deltaTotals.assertions.failed++;
+                deltaTotals.testCases.passed--;
+                deltaTotals.testCases.failed++;
+            }
+            m_totals.testCases += deltaTotals.testCases;
+            m_reporter->testCaseEnded( TestCaseStats(   testInfo,
+                                                        deltaTotals,
+                                                        redirectedCout,
+                                                        redirectedCerr,
+                                                        aborting() ) );
+
+            m_activeTestCase = CATCH_NULL;
+            m_testCaseTracker = CATCH_NULL;
+
+            return deltaTotals;
+        }
+
+        Ptr<IConfig const> config() const {
+            return m_config;
+        }
+
+    private: // IResultCapture
+
+        virtual void assertionEnded( AssertionResult const& result ) {
+            if( result.getResultType() == ResultWas::Ok ) {
+                m_totals.assertions.passed++;
+            }
+            else if( !result.isOk() ) {
+                m_totals.assertions.failed++;
+            }
+
+            // We have no use for the return value (whether messages should be cleared), because messages were made scoped
+            // and should be let to clear themselves out.
+            static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
+
+            // Reset working state
+            m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
+            m_lastResult = result;
+        }
+
+        virtual bool sectionStarted (
+            SectionInfo const& sectionInfo,
+            Counts& assertions
+        )
+        {
+            ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
+            if( !sectionTracker.isOpen() )
+                return false;
+            m_activeSections.push_back( &sectionTracker );
+
+            m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
+
+            m_reporter->sectionStarting( sectionInfo );
+
+            assertions = m_totals.assertions;
+
+            return true;
+        }
+        bool testForMissingAssertions( Counts& assertions ) {
+            if( assertions.total() != 0 )
+                return false;
+            if( !m_config->warnAboutMissingAssertions() )
+                return false;
+            if( m_trackerContext.currentTracker().hasChildren() )
+                return false;
+            m_totals.assertions.failed++;
+            assertions.failed++;
+            return true;
+        }
+
+        virtual void sectionEnded( SectionEndInfo const& endInfo ) {
+            Counts assertions = m_totals.assertions - endInfo.prevAssertions;
+            bool missingAssertions = testForMissingAssertions( assertions );
+
+            if( !m_activeSections.empty() ) {
+                m_activeSections.back()->close();
+                m_activeSections.pop_back();
+            }
+
+            m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
+            m_messages.clear();
+        }
+
+        virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
+            if( m_unfinishedSections.empty() )
+                m_activeSections.back()->fail();
+            else
+                m_activeSections.back()->close();
+            m_activeSections.pop_back();
+
+            m_unfinishedSections.push_back( endInfo );
+        }
+
+        virtual void pushScopedMessage( MessageInfo const& message ) {
+            m_messages.push_back( message );
+        }
+
+        virtual void popScopedMessage( MessageInfo const& message ) {
+            m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
+        }
+
+        virtual std::string getCurrentTestName() const {
+            return m_activeTestCase
+                ? m_activeTestCase->getTestCaseInfo().name
+                : std::string();
+        }
+
+        virtual const AssertionResult* getLastResult() const {
+            return &m_lastResult;
+        }
+
+        virtual void exceptionEarlyReported() {
+            m_shouldReportUnexpected = false;
+        }
+
+        virtual void handleFatalErrorCondition( std::string const& message ) {
+            // Don't rebuild the result -- the stringification itself can cause more fatal errors
+            // Instead, fake a result data.
+            AssertionResultData tempResult;
+            tempResult.resultType = ResultWas::FatalErrorCondition;
+            tempResult.message = message;
+            AssertionResult result(m_lastAssertionInfo, tempResult);
+
+            getResultCapture().assertionEnded(result);
+
+            handleUnfinishedSections();
+
+            // Recreate section for test case (as we will lose the one that was in scope)
+            TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
+            SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
+
+            Counts assertions;
+            assertions.failed = 1;
+            SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
+            m_reporter->sectionEnded( testCaseSectionStats );
+
+            TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
+
+            Totals deltaTotals;
+            deltaTotals.testCases.failed = 1;
+            m_reporter->testCaseEnded( TestCaseStats(   testInfo,
+                                                        deltaTotals,
+                                                        std::string(),
+                                                        std::string(),
+                                                        false ) );
+            m_totals.testCases.failed++;
+            testGroupEnded( std::string(), m_totals, 1, 1 );
+            m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
+        }
+
+    public:
+        // !TBD We need to do this another way!
+        bool aborting() const {
+            return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
+        }
+
+    private:
+
+        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
+            TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
+            SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
+            m_reporter->sectionStarting( testCaseSection );
+            Counts prevAssertions = m_totals.assertions;
+            double duration = 0;
+            m_shouldReportUnexpected = true;
+            try {
+                m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
+
+                seedRng( *m_config );
+
+                Timer timer;
+                timer.start();
+                if( m_reporter->getPreferences().shouldRedirectStdOut ) {
+                    StreamRedirect coutRedir( Catch::cout(), redirectedCout );
+                    StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
+                    invokeActiveTestCase();
+                }
+                else {
+                    invokeActiveTestCase();
+                }
+                duration = timer.getElapsedSeconds();
+            }
+            catch( TestFailureException& ) {
+                // This just means the test was aborted due to failure
+            }
+            catch(...) {
+                // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
+                // are reported without translation at the point of origin.
+                if (m_shouldReportUnexpected) {
+                    makeUnexpectedResultBuilder().useActiveException();
+                }
+            }
+            m_testCaseTracker->close();
+            handleUnfinishedSections();
+            m_messages.clear();
+
+            Counts assertions = m_totals.assertions - prevAssertions;
+            bool missingAssertions = testForMissingAssertions( assertions );
+
+            if( testCaseInfo.okToFail() ) {
+                std::swap( assertions.failedButOk, assertions.failed );
+                m_totals.assertions.failed -= assertions.failedButOk;
+                m_totals.assertions.failedButOk += assertions.failedButOk;
+            }
+
+            SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
+            m_reporter->sectionEnded( testCaseSectionStats );
+        }
+
+        void invokeActiveTestCase() {
+            FatalConditionHandler fatalConditionHandler; // Handle signals
+            m_activeTestCase->invoke();
+            fatalConditionHandler.reset();
+        }
+
+    private:
+
+        ResultBuilder makeUnexpectedResultBuilder() const {
+            return ResultBuilder(   m_lastAssertionInfo.macroName.c_str(),
+                                    m_lastAssertionInfo.lineInfo,
+                                    m_lastAssertionInfo.capturedExpression.c_str(),
+                                    m_lastAssertionInfo.resultDisposition );
+        }
+
+        void handleUnfinishedSections() {
+            // If sections ended prematurely due to an exception we stored their
+            // infos here so we can tear them down outside the unwind process.
+            for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
+                        itEnd = m_unfinishedSections.rend();
+                    it != itEnd;
+                    ++it )
+                sectionEnded( *it );
+            m_unfinishedSections.clear();
+        }
+
+        TestRunInfo m_runInfo;
+        IMutableContext& m_context;
+        TestCase const* m_activeTestCase;
+        ITracker* m_testCaseTracker;
+        ITracker* m_currentSectionTracker;
+        AssertionResult m_lastResult;
+
+        Ptr<IConfig const> m_config;
+        Totals m_totals;
+        Ptr<IStreamingReporter> m_reporter;
+        std::vector<MessageInfo> m_messages;
+        AssertionInfo m_lastAssertionInfo;
+        std::vector<SectionEndInfo> m_unfinishedSections;
+        std::vector<ITracker*> m_activeSections;
+        TrackerContext m_trackerContext;
+        bool m_shouldReportUnexpected;
+    };
+
+    IResultCapture& getResultCapture() {
+        if( IResultCapture* capture = getCurrentContext().getResultCapture() )
+            return *capture;
+        else
+            throw std::logic_error( "No result capture instance" );
+    }
+
+} // end namespace Catch
+
+// #included from: internal/catch_version.h
+#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
+
+namespace Catch {
+
+    // Versioning information
+    struct Version {
+        Version(    unsigned int _majorVersion,
+                    unsigned int _minorVersion,
+                    unsigned int _patchNumber,
+                    char const * const _branchName,
+                    unsigned int _buildNumber );
+
+        unsigned int const majorVersion;
+        unsigned int const minorVersion;
+        unsigned int const patchNumber;
+
+        // buildNumber is only used if branchName is not null
+        char const * const branchName;
+        unsigned int const buildNumber;
+
+        friend std::ostream& operator << ( std::ostream& os, Version const& version );
+
+    private:
+        void operator=( Version const& );
+    };
+
+    inline Version libraryVersion();
+}
+
+#include <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+    Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
+        Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
+        if( !reporter ) {
+            std::ostringstream oss;
+            oss << "No reporter registered with name: '" << reporterName << "'";
+            throw std::domain_error( oss.str() );
+        }
+        return reporter;
+    }
+
+    Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
+        std::vector<std::string> reporters = config->getReporterNames();
+        if( reporters.empty() )
+            reporters.push_back( "console" );
+
+        Ptr<IStreamingReporter> reporter;
+        for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
+                it != itEnd;
+                ++it )
+            reporter = addReporter( reporter, createReporter( *it, config ) );
+        return reporter;
+    }
+    Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
+        IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
+        for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
+                it != itEnd;
+                ++it )
+            reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
+        return reporters;
+    }
+
+    Totals runTests( Ptr<Config> const& config ) {
+
+        Ptr<IConfig const> iconfig = config.get();
+
+        Ptr<IStreamingReporter> reporter = makeReporter( config );
+        reporter = addListeners( iconfig, reporter );
+
+        RunContext context( iconfig, reporter );
+
+        Totals totals;
+
+        context.testGroupStarting( config->name(), 1, 1 );
+
+        TestSpec testSpec = config->testSpec();
+        if( !testSpec.hasFilters() )
+            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
+
+        std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
+        for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
+                it != itEnd;
+                ++it ) {
+            if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
+                totals += context.runTest( *it );
+            else
+                reporter->skipTest( *it );
+        }
+
+        context.testGroupEnded( iconfig->name(), totals, 1, 1 );
+        return totals;
+    }
+
+    void applyFilenamesAsTags( IConfig const& config ) {
+        std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
+        for(std::size_t i = 0; i < tests.size(); ++i ) {
+            TestCase& test = const_cast<TestCase&>( tests[i] );
+            std::set<std::string> tags = test.tags;
+
+            std::string filename = test.lineInfo.file;
+            std::string::size_type lastSlash = filename.find_last_of( "\\/" );
+            if( lastSlash != std::string::npos )
+                filename = filename.substr( lastSlash+1 );
+
+            std::string::size_type lastDot = filename.find_last_of( "." );
+            if( lastDot != std::string::npos )
+                filename = filename.substr( 0, lastDot );
+
+            tags.insert( "#" + filename );
+            setTags( test, tags );
+        }
+    }
+
+    class Session : NonCopyable {
+        static bool alreadyInstantiated;
+
+    public:
+
+        struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
+
+        Session()
+        : m_cli( makeCommandLineParser() ) {
+            if( alreadyInstantiated ) {
+                std::string msg = "Only one instance of Catch::Session can ever be used";
+                Catch::cerr() << msg << std::endl;
+                throw std::logic_error( msg );
+            }
+            alreadyInstantiated = true;
+        }
+        ~Session() {
+            Catch::cleanUp();
+        }
+
+        void showHelp( std::string const& processName ) {
+            Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
+
+            m_cli.usage( Catch::cout(), processName );
+            Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
+        }
+
+        int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
+            try {
+                m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
+                m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
+                if( m_configData.showHelp )
+                    showHelp( m_configData.processName );
+                m_config.reset();
+            }
+            catch( std::exception& ex ) {
+                {
+                    Colour colourGuard( Colour::Red );
+                    Catch::cerr()
+                        << "\nError(s) in input:\n"
+                        << Text( ex.what(), TextAttributes().setIndent(2) )
+                        << "\n\n";
+                }
+                m_cli.usage( Catch::cout(), m_configData.processName );
+                return (std::numeric_limits<int>::max)();
+            }
+            return 0;
+        }
+
+        void useConfigData( ConfigData const& _configData ) {
+            m_configData = _configData;
+            m_config.reset();
+        }
+
+        int run( int argc, char const* const* const argv ) {
+
+            int returnCode = applyCommandLine( argc, argv );
+            if( returnCode == 0 )
+                returnCode = run();
+            return returnCode;
+        }
+
+    #if defined(WIN32) && defined(UNICODE)
+        int run( int argc, wchar_t const* const* const argv ) {
+
+            char **utf8Argv = new char *[ argc ];
+
+            for ( int i = 0; i < argc; ++i ) {
+                int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
+
+                utf8Argv[ i ] = new char[ bufSize ];
+
+                WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
+            }
+
+            int returnCode = applyCommandLine( argc, utf8Argv );
+            if( returnCode == 0 )
+                returnCode = run();
+
+            for ( int i = 0; i < argc; ++i )
+                delete [] utf8Argv[ i ];
+
+            delete [] utf8Argv;
+
+            return returnCode;
+        }
+    #endif
+
+        int run() {
+            if( m_configData.showHelp )
+                return 0;
+
+            try
+            {
+                config(); // Force config to be constructed
+
+                seedRng( *m_config );
+
+                if( m_configData.filenamesAsTags )
+                    applyFilenamesAsTags( *m_config );
+
+                // Handle list request
+                if( Option<std::size_t> listed = list( config() ) )
+                    return static_cast<int>( *listed );
+
+                return static_cast<int>( runTests( m_config ).assertions.failed );
+            }
+            catch( std::exception& ex ) {
+                Catch::cerr() << ex.what() << std::endl;
+                return (std::numeric_limits<int>::max)();
+            }
+        }
+
+        Clara::CommandLine<ConfigData> const& cli() const {
+            return m_cli;
+        }
+        std::vector<Clara::Parser::Token> const& unusedTokens() const {
+            return m_unusedTokens;
+        }
+        ConfigData& configData() {
+            return m_configData;
+        }
+        Config& config() {
+            if( !m_config )
+                m_config = new Config( m_configData );
+            return *m_config;
+        }
+    private:
+        Clara::CommandLine<ConfigData> m_cli;
+        std::vector<Clara::Parser::Token> m_unusedTokens;
+        ConfigData m_configData;
+        Ptr<Config> m_config;
+    };
+
+    bool Session::alreadyInstantiated = false;
+
+} // end namespace Catch
+
+// #included from: catch_registry_hub.hpp
+#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
+
+// #included from: catch_test_case_registry_impl.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <set>
+#include <sstream>
+#include <algorithm>
+
+namespace Catch {
+
+    struct RandomNumberGenerator {
+        typedef std::ptrdiff_t result_type;
+
+        result_type operator()( result_type n ) const { return std::rand() % n; }
+
+#ifdef CATCH_CONFIG_CPP11_SHUFFLE
+        static constexpr result_type min() { return 0; }
+        static constexpr result_type max() { return 1000000; }
+        result_type operator()() const { return std::rand() % max(); }
+#endif
+        template<typename V>
+        static void shuffle( V& vector ) {
+            RandomNumberGenerator rng;
+#ifdef CATCH_CONFIG_CPP11_SHUFFLE
+            std::shuffle( vector.begin(), vector.end(), rng );
+#else
+            std::random_shuffle( vector.begin(), vector.end(), rng );
+#endif
+        }
+    };
+
+    inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+
+        std::vector<TestCase> sorted = unsortedTestCases;
+
+        switch( config.runOrder() ) {
+            case RunTests::InLexicographicalOrder:
+                std::sort( sorted.begin(), sorted.end() );
+                break;
+            case RunTests::InRandomOrder:
+                {
+                    seedRng( config );
+                    RandomNumberGenerator::shuffle( sorted );
+                }
+                break;
+            case RunTests::InDeclarationOrder:
+                // already in declaration order
+                break;
+        }
+        return sorted;
+    }
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
+        return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
+    }
+
+    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
+        std::set<TestCase> seenFunctions;
+        for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
+            it != itEnd;
+            ++it ) {
+            std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
+            if( !prev.second ) {
+                std::ostringstream ss;
+
+                ss  << Colour( Colour::Red )
+                    << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
+                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
+                    << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
+
+                throw std::runtime_error(ss.str());
+            }
+        }
+    }
+
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
+        std::vector<TestCase> filtered;
+        filtered.reserve( testCases.size() );
+        for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
+                it != itEnd;
+                ++it )
+            if( matchTest( *it, testSpec, config ) )
+                filtered.push_back( *it );
+        return filtered;
+    }
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
+        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
+    }
+
+    class TestRegistry : public ITestCaseRegistry {
+    public:
+        TestRegistry()
+        :   m_currentSortOrder( RunTests::InDeclarationOrder ),
+            m_unnamedCount( 0 )
+        {}
+        virtual ~TestRegistry();
+
+        virtual void registerTest( TestCase const& testCase ) {
+            std::string name = testCase.getTestCaseInfo().name;
+            if( name.empty() ) {
+                std::ostringstream oss;
+                oss << "Anonymous test case " << ++m_unnamedCount;
+                return registerTest( testCase.withName( oss.str() ) );
+            }
+            m_functions.push_back( testCase );
+        }
+
+        virtual std::vector<TestCase> const& getAllTests() const {
+            return m_functions;
+        }
+        virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
+            if( m_sortedFunctions.empty() )
+                enforceNoDuplicateTestCases( m_functions );
+
+            if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
+                m_sortedFunctions = sortTests( config, m_functions );
+                m_currentSortOrder = config.runOrder();
+            }
+            return m_sortedFunctions;
+        }
+
+    private:
+        std::vector<TestCase> m_functions;
+        mutable RunTests::InWhatOrder m_currentSortOrder;
+        mutable std::vector<TestCase> m_sortedFunctions;
+        size_t m_unnamedCount;
+        std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+    public:
+
+        FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
+
+        virtual void invoke() const {
+            m_fun();
+        }
+
+    private:
+        virtual ~FreeFunctionTestCase();
+
+        TestFunction m_fun;
+    };
+
+    inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+        std::string className = classOrQualifiedMethodName;
+        if( startsWith( className, '&' ) )
+        {
+            std::size_t lastColons = className.rfind( "::" );
+            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
+            if( penultimateColons == std::string::npos )
+                penultimateColons = 1;
+            className = className.substr( penultimateColons, lastColons-penultimateColons );
+        }
+        return className;
+    }
+
+    void registerTestCase
+        (   ITestCase* testCase,
+            char const* classOrQualifiedMethodName,
+            NameAndDesc const& nameAndDesc,
+            SourceLineInfo const& lineInfo ) {
+
+        getMutableRegistryHub().registerTest
+            ( makeTestCase
+                (   testCase,
+                    extractClassName( classOrQualifiedMethodName ),
+                    nameAndDesc.name,
+                    nameAndDesc.description,
+                    lineInfo ) );
+    }
+    void registerTestCaseFunction
+        (   TestFunction function,
+            SourceLineInfo const& lineInfo,
+            NameAndDesc const& nameAndDesc ) {
+        registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    AutoReg::AutoReg
+        (   TestFunction function,
+            SourceLineInfo const& lineInfo,
+            NameAndDesc const& nameAndDesc ) {
+        registerTestCaseFunction( function, lineInfo, nameAndDesc );
+    }
+
+    AutoReg::~AutoReg() {}
+
+} // end namespace Catch
+
+// #included from: catch_reporter_registry.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+
+#include <map>
+
+namespace Catch {
+
+    class ReporterRegistry : public IReporterRegistry {
+
+    public:
+
+        virtual ~ReporterRegistry() CATCH_OVERRIDE {}
+
+        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
+            FactoryMap::const_iterator it =  m_factories.find( name );
+            if( it == m_factories.end() )
+                return CATCH_NULL;
+            return it->second->create( ReporterConfig( config ) );
+        }
+
+        void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
+            m_factories.insert( std::make_pair( name, factory ) );
+        }
+        void registerListener( Ptr<IReporterFactory> const& factory ) {
+            m_listeners.push_back( factory );
+        }
+
+        virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
+            return m_factories;
+        }
+        virtual Listeners const& getListeners() const CATCH_OVERRIDE {
+            return m_listeners;
+        }
+
+    private:
+        FactoryMap m_factories;
+        Listeners m_listeners;
+    };
+}
+
+// #included from: catch_exception_translator_registry.hpp
+#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
+
+#ifdef __OBJC__
+#import "Foundation/Foundation.h"
+#endif
+
+namespace Catch {
+
+    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
+    public:
+        ~ExceptionTranslatorRegistry() {
+            deleteAll( m_translators );
+        }
+
+        virtual void registerTranslator( const IExceptionTranslator* translator ) {
+            m_translators.push_back( translator );
+        }
+
+        virtual std::string translateActiveException() const {
+            try {
+#ifdef __OBJC__
+                // In Objective-C try objective-c exceptions first
+                @try {
+                    return tryTranslators();
+                }
+                @catch (NSException *exception) {
+                    return Catch::toString( [exception description] );
+                }
+#else
+                return tryTranslators();
+#endif
+            }
+            catch( TestFailureException& ) {
+                throw;
+            }
+            catch( std::exception& ex ) {
+                return ex.what();
+            }
+            catch( std::string& msg ) {
+                return msg;
+            }
+            catch( const char* msg ) {
+                return msg;
+            }
+            catch(...) {
+                return "Unknown exception";
+            }
+        }
+
+        std::string tryTranslators() const {
+            if( m_translators.empty() )
+                throw;
+            else
+                return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
+        }
+
+    private:
+        std::vector<const IExceptionTranslator*> m_translators;
+    };
+}
+
+// #included from: catch_tag_alias_registry.h
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
+
+#include <map>
+
+namespace Catch {
+
+    class TagAliasRegistry : public ITagAliasRegistry {
+    public:
+        virtual ~TagAliasRegistry();
+        virtual Option<TagAlias> find( std::string const& alias ) const;
+        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
+        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
+
+    private:
+        std::map<std::string, TagAlias> m_registry;
+    };
+
+} // end namespace Catch
+
+namespace Catch {
+
+    namespace {
+
+        class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
+
+            RegistryHub( RegistryHub const& );
+            void operator=( RegistryHub const& );
+
+        public: // IRegistryHub
+            RegistryHub() {
+            }
+            virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
+                return m_reporterRegistry;
+            }
+            virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
+                return m_testCaseRegistry;
+            }
+            virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
+                return m_exceptionTranslatorRegistry;
+            }
+            virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
+                return m_tagAliasRegistry;
+            }
+
+        public: // IMutableRegistryHub
+            virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
+                m_reporterRegistry.registerReporter( name, factory );
+            }
+            virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
+                m_reporterRegistry.registerListener( factory );
+            }
+            virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
+                m_testCaseRegistry.registerTest( testInfo );
+            }
+            virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
+                m_exceptionTranslatorRegistry.registerTranslator( translator );
+            }
+            virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE {
+                m_tagAliasRegistry.add( alias, tag, lineInfo );
+            }
+
+        private:
+            TestRegistry m_testCaseRegistry;
+            ReporterRegistry m_reporterRegistry;
+            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
+            TagAliasRegistry m_tagAliasRegistry;
+        };
+
+        // Single, global, instance
+        inline RegistryHub*& getTheRegistryHub() {
+            static RegistryHub* theRegistryHub = CATCH_NULL;
+            if( !theRegistryHub )
+                theRegistryHub = new RegistryHub();
+            return theRegistryHub;
+        }
+    }
+
+    IRegistryHub& getRegistryHub() {
+        return *getTheRegistryHub();
+    }
+    IMutableRegistryHub& getMutableRegistryHub() {
+        return *getTheRegistryHub();
+    }
+    void cleanUp() {
+        delete getTheRegistryHub();
+        getTheRegistryHub() = CATCH_NULL;
+        cleanUpContext();
+    }
+    std::string translateActiveException() {
+        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_notimplemented_exception.hpp
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
+
+#include <sstream>
+
+namespace Catch {
+
+    NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
+    :   m_lineInfo( lineInfo ) {
+        std::ostringstream oss;
+        oss << lineInfo << ": function ";
+        oss << "not implemented";
+        m_what = oss.str();
+    }
+
+    const char* NotImplementedException::what() const CATCH_NOEXCEPT {
+        return m_what.c_str();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_context_impl.hpp
+#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
+
+// #included from: catch_stream.hpp
+#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
+
+#include <stdexcept>
+#include <cstdio>
+#include <iostream>
+
+namespace Catch {
+
+    template<typename WriterF, size_t bufferSize=256>
+    class StreamBufImpl : public StreamBufBase {
+        char data[bufferSize];
+        WriterF m_writer;
+
+    public:
+        StreamBufImpl() {
+            setp( data, data + sizeof(data) );
+        }
+
+        ~StreamBufImpl() CATCH_NOEXCEPT {
+            sync();
+        }
+
+    private:
+        int overflow( int c ) {
+            sync();
+
+            if( c != EOF ) {
+                if( pbase() == epptr() )
+                    m_writer( std::string( 1, static_cast<char>( c ) ) );
+                else
+                    sputc( static_cast<char>( c ) );
+            }
+            return 0;
+        }
+
+        int sync() {
+            if( pbase() != pptr() ) {
+                m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
+                setp( pbase(), epptr() );
+            }
+            return 0;
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    FileStream::FileStream( std::string const& filename ) {
+        m_ofs.open( filename.c_str() );
+        if( m_ofs.fail() ) {
+            std::ostringstream oss;
+            oss << "Unable to open file: '" << filename << '\'';
+            throw std::domain_error( oss.str() );
+        }
+    }
+
+    std::ostream& FileStream::stream() const {
+        return m_ofs;
+    }
+
+    struct OutputDebugWriter {
+
+        void operator()( std::string const&str ) {
+            writeToDebugConsole( str );
+        }
+    };
+
+    DebugOutStream::DebugOutStream()
+    :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
+        m_os( m_streamBuf.get() )
+    {}
+
+    std::ostream& DebugOutStream::stream() const {
+        return m_os;
+    }
+
+    // Store the streambuf from cout up-front because
+    // cout may get redirected when running tests
+    CoutStream::CoutStream()
+    :   m_os( Catch::cout().rdbuf() )
+    {}
+
+    std::ostream& CoutStream::stream() const {
+        return m_os;
+    }
+
+#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
+    std::ostream& cout() {
+        return std::cout;
+    }
+    std::ostream& cerr() {
+        return std::cerr;
+    }
+#endif
+}
+
+namespace Catch {
+
+    class Context : public IMutableContext {
+
+        Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
+        Context( Context const& );
+        void operator=( Context const& );
+
+    public:
+        virtual ~Context() {
+            deleteAllValues( m_generatorsByTestName );
+        }
+
+    public: // IContext
+        virtual IResultCapture* getResultCapture() {
+            return m_resultCapture;
+        }
+        virtual IRunner* getRunner() {
+            return m_runner;
+        }
+        virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
+            return getGeneratorsForCurrentTest()
+            .getGeneratorInfo( fileInfo, totalSize )
+            .getCurrentIndex();
+        }
+        virtual bool advanceGeneratorsForCurrentTest() {
+            IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+            return generators && generators->moveNext();
+        }
+
+        virtual Ptr<IConfig const> getConfig() const {
+            return m_config;
+        }
+
+    public: // IMutableContext
+        virtual void setResultCapture( IResultCapture* resultCapture ) {
+            m_resultCapture = resultCapture;
+        }
+        virtual void setRunner( IRunner* runner ) {
+            m_runner = runner;
+        }
+        virtual void setConfig( Ptr<IConfig const> const& config ) {
+            m_config = config;
+        }
+
+        friend IMutableContext& getCurrentMutableContext();
+
+    private:
+        IGeneratorsForTest* findGeneratorsForCurrentTest() {
+            std::string testName = getResultCapture()->getCurrentTestName();
+
+            std::map<std::string, IGeneratorsForTest*>::const_iterator it =
+                m_generatorsByTestName.find( testName );
+            return it != m_generatorsByTestName.end()
+                ? it->second
+                : CATCH_NULL;
+        }
+
+        IGeneratorsForTest& getGeneratorsForCurrentTest() {
+            IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+            if( !generators ) {
+                std::string testName = getResultCapture()->getCurrentTestName();
+                generators = createGeneratorsForTest();
+                m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
+            }
+            return *generators;
+        }
+
+    private:
+        Ptr<IConfig const> m_config;
+        IRunner* m_runner;
+        IResultCapture* m_resultCapture;
+        std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
+    };
+
+    namespace {
+        Context* currentContext = CATCH_NULL;
+    }
+    IMutableContext& getCurrentMutableContext() {
+        if( !currentContext )
+            currentContext = new Context();
+        return *currentContext;
+    }
+    IContext& getCurrentContext() {
+        return getCurrentMutableContext();
+    }
+
+    void cleanUpContext() {
+        delete currentContext;
+        currentContext = CATCH_NULL;
+    }
+}
+
+// #included from: catch_console_colour_impl.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
+
+// #included from: catch_errno_guard.hpp
+#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
+
+#include <cerrno>
+
+namespace Catch {
+
+    class ErrnoGuard {
+    public:
+        ErrnoGuard():m_oldErrno(errno){}
+        ~ErrnoGuard() { errno = m_oldErrno; }
+    private:
+        int m_oldErrno;
+    };
+
+}
+
+namespace Catch {
+    namespace {
+
+        struct IColourImpl {
+            virtual ~IColourImpl() {}
+            virtual void use( Colour::Code _colourCode ) = 0;
+        };
+
+        struct NoColourImpl : IColourImpl {
+            void use( Colour::Code ) {}
+
+            static IColourImpl* instance() {
+                static NoColourImpl s_instance;
+                return &s_instance;
+            }
+        };
+
+    } // anon namespace
+} // namespace Catch
+
+#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
+#   ifdef CATCH_PLATFORM_WINDOWS
+#       define CATCH_CONFIG_COLOUR_WINDOWS
+#   else
+#       define CATCH_CONFIG_COLOUR_ANSI
+#   endif
+#endif
+
+#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
+
+namespace Catch {
+namespace {
+
+    class Win32ColourImpl : public IColourImpl {
+    public:
+        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
+        {
+            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
+            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
+            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
+        }
+
+        virtual void use( Colour::Code _colourCode ) {
+            switch( _colourCode ) {
+                case Colour::None:      return setTextAttribute( originalForegroundAttributes );
+                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
+                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
+                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
+                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
+                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
+                case Colour::Grey:      return setTextAttribute( 0 );
+
+                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
+                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
+                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
+                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+
+                case Colour::Bright: throw std::logic_error( "not a colour" );
+            }
+        }
+
+    private:
+        void setTextAttribute( WORD _textAttribute ) {
+            SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
+        }
+        HANDLE stdoutHandle;
+        WORD originalForegroundAttributes;
+        WORD originalBackgroundAttributes;
+    };
+
+    IColourImpl* platformColourInstance() {
+        static Win32ColourImpl s_instance;
+
+        Ptr<IConfig const> config = getCurrentContext().getConfig();
+        UseColour::YesOrNo colourMode = config
+            ? config->useColour()
+            : UseColour::Auto;
+        if( colourMode == UseColour::Auto )
+            colourMode = !isDebuggerActive()
+                ? UseColour::Yes
+                : UseColour::No;
+        return colourMode == UseColour::Yes
+            ? &s_instance
+            : NoColourImpl::instance();
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
+
+#include <unistd.h>
+
+namespace Catch {
+namespace {
+
+    // use POSIX/ ANSI console terminal codes
+    // Thanks to Adam Strzelecki for original contribution
+    // (http://github.com/nanoant)
+    // https://github.com/philsquared/Catch/pull/131
+    class PosixColourImpl : public IColourImpl {
+    public:
+        virtual void use( Colour::Code _colourCode ) {
+            switch( _colourCode ) {
+                case Colour::None:
+                case Colour::White:     return setColour( "[0m" );
+                case Colour::Red:       return setColour( "[0;31m" );
+                case Colour::Green:     return setColour( "[0;32m" );
+                case Colour::Blue:      return setColour( "[0;34m" );
+                case Colour::Cyan:      return setColour( "[0;36m" );
+                case Colour::Yellow:    return setColour( "[0;33m" );
+                case Colour::Grey:      return setColour( "[1;30m" );
+
+                case Colour::LightGrey:     return setColour( "[0;37m" );
+                case Colour::BrightRed:     return setColour( "[1;31m" );
+                case Colour::BrightGreen:   return setColour( "[1;32m" );
+                case Colour::BrightWhite:   return setColour( "[1;37m" );
+
+                case Colour::Bright: throw std::logic_error( "not a colour" );
+            }
+        }
+        static IColourImpl* instance() {
+            static PosixColourImpl s_instance;
+            return &s_instance;
+        }
+
+    private:
+        void setColour( const char* _escapeCode ) {
+            Catch::cout() << '\033' << _escapeCode;
+        }
+    };
+
+    IColourImpl* platformColourInstance() {
+        ErrnoGuard guard;
+        Ptr<IConfig const> config = getCurrentContext().getConfig();
+        UseColour::YesOrNo colourMode = config
+            ? config->useColour()
+            : UseColour::Auto;
+        if( colourMode == UseColour::Auto )
+            colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
+                ? UseColour::Yes
+                : UseColour::No;
+        return colourMode == UseColour::Yes
+            ? PosixColourImpl::instance()
+            : NoColourImpl::instance();
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#else  // not Windows or ANSI ///////////////////////////////////////////////
+
+namespace Catch {
+
+    static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
+
+} // end namespace Catch
+
+#endif // Windows/ ANSI/ None
+
+namespace Catch {
+
+    Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
+    Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
+    Colour::~Colour(){ if( !m_moved ) use( None ); }
+
+    void Colour::use( Code _colourCode ) {
+        static IColourImpl* impl = platformColourInstance();
+        impl->use( _colourCode );
+    }
+
+} // end namespace Catch
+
+// #included from: catch_generators_impl.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <string>
+#include <map>
+
+namespace Catch {
+
+    struct GeneratorInfo : IGeneratorInfo {
+
+        GeneratorInfo( std::size_t size )
+        :   m_size( size ),
+            m_currentIndex( 0 )
+        {}
+
+        bool moveNext() {
+            if( ++m_currentIndex == m_size ) {
+                m_currentIndex = 0;
+                return false;
+            }
+            return true;
+        }
+
+        std::size_t getCurrentIndex() const {
+            return m_currentIndex;
+        }
+
+        std::size_t m_size;
+        std::size_t m_currentIndex;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class GeneratorsForTest : public IGeneratorsForTest {
+
+    public:
+        ~GeneratorsForTest() {
+            deleteAll( m_generatorsInOrder );
+        }
+
+        IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
+            std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
+            if( it == m_generatorsByName.end() ) {
+                IGeneratorInfo* info = new GeneratorInfo( size );
+                m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
+                m_generatorsInOrder.push_back( info );
+                return *info;
+            }
+            return *it->second;
+        }
+
+        bool moveNext() {
+            std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+            std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+            for(; it != itEnd; ++it ) {
+                if( (*it)->moveNext() )
+                    return true;
+            }
+            return false;
+        }
+
+    private:
+        std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+        std::vector<IGeneratorInfo*> m_generatorsInOrder;
+    };
+
+    IGeneratorsForTest* createGeneratorsForTest()
+    {
+        return new GeneratorsForTest();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.hpp
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
+
+namespace Catch {
+
+    AssertionInfo::AssertionInfo(   std::string const& _macroName,
+                                    SourceLineInfo const& _lineInfo,
+                                    std::string const& _capturedExpression,
+                                    ResultDisposition::Flags _resultDisposition )
+    :   macroName( _macroName ),
+        lineInfo( _lineInfo ),
+        capturedExpression( _capturedExpression ),
+        resultDisposition( _resultDisposition )
+    {}
+
+    AssertionResult::AssertionResult() {}
+
+    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
+    :   m_info( info ),
+        m_resultData( data )
+    {}
+
+    AssertionResult::~AssertionResult() {}
+
+    // Result was a success
+    bool AssertionResult::succeeded() const {
+        return Catch::isOk( m_resultData.resultType );
+    }
+
+    // Result was a success, or failure is suppressed
+    bool AssertionResult::isOk() const {
+        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
+    }
+
+    ResultWas::OfType AssertionResult::getResultType() const {
+        return m_resultData.resultType;
+    }
+
+    bool AssertionResult::hasExpression() const {
+        return !m_info.capturedExpression.empty();
+    }
+
+    bool AssertionResult::hasMessage() const {
+        return !m_resultData.message.empty();
+    }
+
+    std::string AssertionResult::getExpression() const {
+        if( isFalseTest( m_info.resultDisposition ) )
+            return '!' + m_info.capturedExpression;
+        else
+            return m_info.capturedExpression;
+    }
+    std::string AssertionResult::getExpressionInMacro() const {
+        if( m_info.macroName.empty() )
+            return m_info.capturedExpression;
+        else
+            return m_info.macroName + "( " + m_info.capturedExpression + " )";
+    }
+
+    bool AssertionResult::hasExpandedExpression() const {
+        return hasExpression() && getExpandedExpression() != getExpression();
+    }
+
+    std::string AssertionResult::getExpandedExpression() const {
+        return m_resultData.reconstructExpression();
+    }
+
+    std::string AssertionResult::getMessage() const {
+        return m_resultData.message;
+    }
+    SourceLineInfo AssertionResult::getSourceInfo() const {
+        return m_info.lineInfo;
+    }
+
+    std::string AssertionResult::getTestMacroName() const {
+        return m_info.macroName;
+    }
+
+    void AssertionResult::discardDecomposedExpression() const {
+        m_resultData.decomposedExpression = CATCH_NULL;
+    }
+
+    void AssertionResult::expandDecomposedExpression() const {
+        m_resultData.reconstructExpression();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_test_case_info.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
+
+#include <cctype>
+
+namespace Catch {
+
+    inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
+        if( startsWith( tag, '.' ) ||
+            tag == "hide" ||
+            tag == "!hide" )
+            return TestCaseInfo::IsHidden;
+        else if( tag == "!throws" )
+            return TestCaseInfo::Throws;
+        else if( tag == "!shouldfail" )
+            return TestCaseInfo::ShouldFail;
+        else if( tag == "!mayfail" )
+            return TestCaseInfo::MayFail;
+        else if( tag == "!nonportable" )
+            return TestCaseInfo::NonPortable;
+        else
+            return TestCaseInfo::None;
+    }
+    inline bool isReservedTag( std::string const& tag ) {
+        return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
+    }
+    inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
+        if( isReservedTag( tag ) ) {
+            std::ostringstream ss;
+            ss << Colour(Colour::Red)
+               << "Tag name [" << tag << "] not allowed.\n"
+               << "Tag names starting with non alpha-numeric characters are reserved\n"
+               << Colour(Colour::FileName)
+               << _lineInfo << '\n';
+            throw std::runtime_error(ss.str());
+        }
+    }
+
+    TestCase makeTestCase(  ITestCase* _testCase,
+                            std::string const& _className,
+                            std::string const& _name,
+                            std::string const& _descOrTags,
+                            SourceLineInfo const& _lineInfo )
+    {
+        bool isHidden( startsWith( _name, "./" ) ); // Legacy support
+
+        // Parse out tags
+        std::set<std::string> tags;
+        std::string desc, tag;
+        bool inTag = false;
+        for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
+            char c = _descOrTags[i];
+            if( !inTag ) {
+                if( c == '[' )
+                    inTag = true;
+                else
+                    desc += c;
+            }
+            else {
+                if( c == ']' ) {
+                    TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
+                    if( prop == TestCaseInfo::IsHidden )
+                        isHidden = true;
+                    else if( prop == TestCaseInfo::None )
+                        enforceNotReservedTag( tag, _lineInfo );
+
+                    tags.insert( tag );
+                    tag.clear();
+                    inTag = false;
+                }
+                else
+                    tag += c;
+            }
+        }
+        if( isHidden ) {
+            tags.insert( "hide" );
+            tags.insert( "." );
+        }
+
+        TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
+        return TestCase( _testCase, info );
+    }
+
+    void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
+    {
+        testCaseInfo.tags = tags;
+        testCaseInfo.lcaseTags.clear();
+
+        std::ostringstream oss;
+        for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
+            oss << '[' << *it << ']';
+            std::string lcaseTag = toLower( *it );
+            testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
+            testCaseInfo.lcaseTags.insert( lcaseTag );
+        }
+        testCaseInfo.tagsAsString = oss.str();
+    }
+
+    TestCaseInfo::TestCaseInfo( std::string const& _name,
+                                std::string const& _className,
+                                std::string const& _description,
+                                std::set<std::string> const& _tags,
+                                SourceLineInfo const& _lineInfo )
+    :   name( _name ),
+        className( _className ),
+        description( _description ),
+        lineInfo( _lineInfo ),
+        properties( None )
+    {
+        setTags( *this, _tags );
+    }
+
+    TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
+    :   name( other.name ),
+        className( other.className ),
+        description( other.description ),
+        tags( other.tags ),
+        lcaseTags( other.lcaseTags ),
+        tagsAsString( other.tagsAsString ),
+        lineInfo( other.lineInfo ),
+        properties( other.properties )
+    {}
+
+    bool TestCaseInfo::isHidden() const {
+        return ( properties & IsHidden ) != 0;
+    }
+    bool TestCaseInfo::throws() const {
+        return ( properties & Throws ) != 0;
+    }
+    bool TestCaseInfo::okToFail() const {
+        return ( properties & (ShouldFail | MayFail ) ) != 0;
+    }
+    bool TestCaseInfo::expectedToFail() const {
+        return ( properties & (ShouldFail ) ) != 0;
+    }
+
+    TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
+
+    TestCase::TestCase( TestCase const& other )
+    :   TestCaseInfo( other ),
+        test( other.test )
+    {}
+
+    TestCase TestCase::withName( std::string const& _newName ) const {
+        TestCase other( *this );
+        other.name = _newName;
+        return other;
+    }
+
+    void TestCase::swap( TestCase& other ) {
+        test.swap( other.test );
+        name.swap( other.name );
+        className.swap( other.className );
+        description.swap( other.description );
+        tags.swap( other.tags );
+        lcaseTags.swap( other.lcaseTags );
+        tagsAsString.swap( other.tagsAsString );
+        std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
+        std::swap( lineInfo, other.lineInfo );
+    }
+
+    void TestCase::invoke() const {
+        test->invoke();
+    }
+
+    bool TestCase::operator == ( TestCase const& other ) const {
+        return  test.get() == other.test.get() &&
+                name == other.name &&
+                className == other.className;
+    }
+
+    bool TestCase::operator < ( TestCase const& other ) const {
+        return name < other.name;
+    }
+    TestCase& TestCase::operator = ( TestCase const& other ) {
+        TestCase temp( other );
+        swap( temp );
+        return *this;
+    }
+
+    TestCaseInfo const& TestCase::getTestCaseInfo() const
+    {
+        return *this;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_version.hpp
+#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
+
+namespace Catch {
+
+    Version::Version
+        (   unsigned int _majorVersion,
+            unsigned int _minorVersion,
+            unsigned int _patchNumber,
+            char const * const _branchName,
+            unsigned int _buildNumber )
+    :   majorVersion( _majorVersion ),
+        minorVersion( _minorVersion ),
+        patchNumber( _patchNumber ),
+        branchName( _branchName ),
+        buildNumber( _buildNumber )
+    {}
+
+    std::ostream& operator << ( std::ostream& os, Version const& version ) {
+        os  << version.majorVersion << '.'
+            << version.minorVersion << '.'
+            << version.patchNumber;
+        // branchName is never null -> 0th char is \0 if it is empty
+        if (version.branchName[0]) {
+            os << '-' << version.branchName
+               << '.' << version.buildNumber;
+        }
+        return os;
+    }
+
+    inline Version libraryVersion() {
+        static Version version( 1, 9, 4, "", 0 );
+        return version;
+    }
+
+}
+
+// #included from: catch_message.hpp
+#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
+
+namespace Catch {
+
+    MessageInfo::MessageInfo(   std::string const& _macroName,
+                                SourceLineInfo const& _lineInfo,
+                                ResultWas::OfType _type )
+    :   macroName( _macroName ),
+        lineInfo( _lineInfo ),
+        type( _type ),
+        sequence( ++globalCount )
+    {}
+
+    // This may need protecting if threading support is added
+    unsigned int MessageInfo::globalCount = 0;
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    ScopedMessage::ScopedMessage( MessageBuilder const& builder )
+    : m_info( builder.m_info )
+    {
+        m_info.message = builder.m_stream.str();
+        getResultCapture().pushScopedMessage( m_info );
+    }
+    ScopedMessage::ScopedMessage( ScopedMessage const& other )
+    : m_info( other.m_info )
+    {}
+
+    ScopedMessage::~ScopedMessage() {
+        if ( !std::uncaught_exception() ){
+            getResultCapture().popScopedMessage(m_info);
+        }
+    }
+
+} // end namespace Catch
+
+// #included from: catch_legacy_reporter_adapter.hpp
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
+
+// #included from: catch_legacy_reporter_adapter.h
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
+
+namespace Catch
+{
+    // Deprecated
+    struct IReporter : IShared {
+        virtual ~IReporter();
+
+        virtual bool shouldRedirectStdout() const = 0;
+
+        virtual void StartTesting() = 0;
+        virtual void EndTesting( Totals const& totals ) = 0;
+        virtual void StartGroup( std::string const& groupName ) = 0;
+        virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
+        virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
+        virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
+        virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
+        virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
+        virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
+        virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
+        virtual void Aborted() = 0;
+        virtual void Result( AssertionResult const& result ) = 0;
+    };
+
+    class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
+    {
+    public:
+        LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
+        virtual ~LegacyReporterAdapter();
+
+        virtual ReporterPreferences getPreferences() const;
+        virtual void noMatchingTestCases( std::string const& );
+        virtual void testRunStarting( TestRunInfo const& );
+        virtual void testGroupStarting( GroupInfo const& groupInfo );
+        virtual void testCaseStarting( TestCaseInfo const& testInfo );
+        virtual void sectionStarting( SectionInfo const& sectionInfo );
+        virtual void assertionStarting( AssertionInfo const& );
+        virtual bool assertionEnded( AssertionStats const& assertionStats );
+        virtual void sectionEnded( SectionStats const& sectionStats );
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats );
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats );
+        virtual void testRunEnded( TestRunStats const& testRunStats );
+        virtual void skipTest( TestCaseInfo const& );
+
+    private:
+        Ptr<IReporter> m_legacyReporter;
+    };
+}
+
+namespace Catch
+{
+    LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
+    :   m_legacyReporter( legacyReporter )
+    {}
+    LegacyReporterAdapter::~LegacyReporterAdapter() {}
+
+    ReporterPreferences LegacyReporterAdapter::getPreferences() const {
+        ReporterPreferences prefs;
+        prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
+        return prefs;
+    }
+
+    void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
+    void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
+        m_legacyReporter->StartTesting();
+    }
+    void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
+        m_legacyReporter->StartGroup( groupInfo.name );
+    }
+    void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
+        m_legacyReporter->StartTestCase( testInfo );
+    }
+    void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
+        m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
+    }
+    void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
+        // Not on legacy interface
+    }
+
+    bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
+        if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
+            for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
+                    it != itEnd;
+                    ++it ) {
+                if( it->type == ResultWas::Info ) {
+                    ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
+                    rb << it->message;
+                    rb.setResultType( ResultWas::Info );
+                    AssertionResult result = rb.build();
+                    m_legacyReporter->Result( result );
+                }
+            }
+        }
+        m_legacyReporter->Result( assertionStats.assertionResult );
+        return true;
+    }
+    void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
+        if( sectionStats.missingAssertions )
+            m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
+        m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
+    }
+    void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        m_legacyReporter->EndTestCase
+            (   testCaseStats.testInfo,
+                testCaseStats.totals,
+                testCaseStats.stdOut,
+                testCaseStats.stdErr );
+    }
+    void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        if( testGroupStats.aborting )
+            m_legacyReporter->Aborted();
+        m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
+    }
+    void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
+        m_legacyReporter->EndTesting( testRunStats.totals );
+    }
+    void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
+    }
+}
+
+// #included from: catch_timer.hpp
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++11-long-long"
+#endif
+
+#ifdef CATCH_PLATFORM_WINDOWS
+
+#else
+
+#include <sys/time.h>
+
+#endif
+
+namespace Catch {
+
+    namespace {
+#ifdef CATCH_PLATFORM_WINDOWS
+        UInt64 getCurrentTicks() {
+            static UInt64 hz=0, hzo=0;
+            if (!hz) {
+                QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
+                QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
+            }
+            UInt64 t;
+            QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
+            return ((t-hzo)*1000000)/hz;
+        }
+#else
+        UInt64 getCurrentTicks() {
+            timeval t;
+            gettimeofday(&t,CATCH_NULL);
+            return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec );
+        }
+#endif
+    }
+
+    void Timer::start() {
+        m_ticks = getCurrentTicks();
+    }
+    unsigned int Timer::getElapsedMicroseconds() const {
+        return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+    }
+    unsigned int Timer::getElapsedMilliseconds() const {
+        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
+    }
+    double Timer::getElapsedSeconds() const {
+        return getElapsedMicroseconds()/1000000.0;
+    }
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+// #included from: catch_common.hpp
+#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
+
+#include <cstring>
+#include <cctype>
+
+namespace Catch {
+
+    bool startsWith( std::string const& s, std::string const& prefix ) {
+        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
+    }
+    bool startsWith( std::string const& s, char prefix ) {
+        return !s.empty() && s[0] == prefix;
+    }
+    bool endsWith( std::string const& s, std::string const& suffix ) {
+        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
+    }
+    bool endsWith( std::string const& s, char suffix ) {
+        return !s.empty() && s[s.size()-1] == suffix;
+    }
+    bool contains( std::string const& s, std::string const& infix ) {
+        return s.find( infix ) != std::string::npos;
+    }
+    char toLowerCh(char c) {
+        return static_cast<char>( std::tolower( c ) );
+    }
+    void toLowerInPlace( std::string& s ) {
+        std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
+    }
+    std::string toLower( std::string const& s ) {
+        std::string lc = s;
+        toLowerInPlace( lc );
+        return lc;
+    }
+    std::string trim( std::string const& str ) {
+        static char const* whitespaceChars = "\n\r\t ";
+        std::string::size_type start = str.find_first_not_of( whitespaceChars );
+        std::string::size_type end = str.find_last_not_of( whitespaceChars );
+
+        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
+    }
+
+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
+        bool replaced = false;
+        std::size_t i = str.find( replaceThis );
+        while( i != std::string::npos ) {
+            replaced = true;
+            str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
+            if( i < str.size()-withThis.size() )
+                i = str.find( replaceThis, i+withThis.size() );
+            else
+                i = std::string::npos;
+        }
+        return replaced;
+    }
+
+    pluralise::pluralise( std::size_t count, std::string const& label )
+    :   m_count( count ),
+        m_label( label )
+    {}
+
+    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
+        os << pluraliser.m_count << ' ' << pluraliser.m_label;
+        if( pluraliser.m_count != 1 )
+            os << 's';
+        return os;
+    }
+
+    SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
+    SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
+    :   file( _file ),
+        line( _line )
+    {}
+    bool SourceLineInfo::empty() const {
+        return file[0] == '\0';
+    }
+    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
+        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
+    }
+    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
+        return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
+    }
+
+    void seedRng( IConfig const& config ) {
+        if( config.rngSeed() != 0 )
+            std::srand( config.rngSeed() );
+    }
+    unsigned int rngSeed() {
+        return getCurrentContext().getConfig()->rngSeed();
+    }
+
+    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
+#ifndef __GNUG__
+        os << info.file << '(' << info.line << ')';
+#else
+        os << info.file << ':' << info.line;
+#endif
+        return os;
+    }
+
+    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
+        std::ostringstream oss;
+        oss << locationInfo << ": Internal Catch error: '" << message << '\'';
+        if( alwaysTrue() )
+            throw std::logic_error( oss.str() );
+    }
+}
+
+// #included from: catch_section.hpp
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+namespace Catch {
+
+    SectionInfo::SectionInfo
+        (   SourceLineInfo const& _lineInfo,
+            std::string const& _name,
+            std::string const& _description )
+    :   name( _name ),
+        description( _description ),
+        lineInfo( _lineInfo )
+    {}
+
+    Section::Section( SectionInfo const& info )
+    :   m_info( info ),
+        m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
+    {
+        m_timer.start();
+    }
+
+    Section::~Section() {
+        if( m_sectionIncluded ) {
+            SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
+            if( std::uncaught_exception() )
+                getResultCapture().sectionEndedEarly( endInfo );
+            else
+                getResultCapture().sectionEnded( endInfo );
+        }
+    }
+
+    // This indicates whether the section should be executed or not
+    Section::operator bool() const {
+        return m_sectionIncluded;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_debugger.hpp
+#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
+
+#ifdef CATCH_PLATFORM_MAC
+
+    #include <assert.h>
+    #include <stdbool.h>
+    #include <sys/types.h>
+    #include <unistd.h>
+    #include <sys/sysctl.h>
+
+    namespace Catch{
+
+        // The following function is taken directly from the following technical note:
+        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+
+        // Returns true if the current process is being debugged (either
+        // running under the debugger or has a debugger attached post facto).
+        bool isDebuggerActive(){
+
+            int                 mib[4];
+            struct kinfo_proc   info;
+            size_t              size;
+
+            // Initialize the flags so that, if sysctl fails for some bizarre
+            // reason, we get a predictable result.
+
+            info.kp_proc.p_flag = 0;
+
+            // Initialize mib, which tells sysctl the info we want, in this case
+            // we're looking for information about a specific process ID.
+
+            mib[0] = CTL_KERN;
+            mib[1] = KERN_PROC;
+            mib[2] = KERN_PROC_PID;
+            mib[3] = getpid();
+
+            // Call sysctl.
+
+            size = sizeof(info);
+            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
+                Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
+                return false;
+            }
+
+            // We're being debugged if the P_TRACED flag is set.
+
+            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
+        }
+    } // namespace Catch
+
+#elif defined(CATCH_PLATFORM_LINUX)
+    #include <fstream>
+    #include <string>
+
+    namespace Catch{
+        // The standard POSIX way of detecting a debugger is to attempt to
+        // ptrace() the process, but this needs to be done from a child and not
+        // this process itself to still allow attaching to this process later
+        // if wanted, so is rather heavy. Under Linux we have the PID of the
+        // "debugger" (which doesn't need to be gdb, of course, it could also
+        // be strace, for example) in /proc/$PID/status, so just get it from
+        // there instead.
+        bool isDebuggerActive(){
+            // Libstdc++ has a bug, where std::ifstream sets errno to 0
+            // This way our users can properly assert over errno values
+            ErrnoGuard guard;
+            std::ifstream in("/proc/self/status");
+            for( std::string line; std::getline(in, line); ) {
+                static const int PREFIX_LEN = 11;
+                if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
+                    // We're traced if the PID is not 0 and no other PID starts
+                    // with 0 digit, so it's enough to check for just a single
+                    // character.
+                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
+                }
+            }
+
+            return false;
+        }
+    } // namespace Catch
+#elif defined(_MSC_VER)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#else
+    namespace Catch {
+       inline bool isDebuggerActive() { return false; }
+    }
+#endif // Platform
+
+#ifdef CATCH_PLATFORM_WINDOWS
+
+    namespace Catch {
+        void writeToDebugConsole( std::string const& text ) {
+            ::OutputDebugStringA( text.c_str() );
+        }
+    }
+#else
+    namespace Catch {
+        void writeToDebugConsole( std::string const& text ) {
+            // !TBD: Need a version for Mac/ XCode and other IDEs
+            Catch::cout() << text;
+        }
+    }
+#endif // Platform
+
+// #included from: catch_tostring.hpp
+#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
+
+namespace Catch {
+
+namespace Detail {
+
+    const std::string unprintableString = "{?}";
+
+    namespace {
+        const int hexThreshold = 255;
+
+        struct Endianness {
+            enum Arch { Big, Little };
+
+            static Arch which() {
+                union _{
+                    int asInt;
+                    char asChar[sizeof (int)];
+                } u;
+
+                u.asInt = 1;
+                return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
+            }
+        };
+    }
+
+    std::string rawMemoryToString( const void *object, std::size_t size )
+    {
+        // Reverse order for little endian architectures
+        int i = 0, end = static_cast<int>( size ), inc = 1;
+        if( Endianness::which() == Endianness::Little ) {
+            i = end-1;
+            end = inc = -1;
+        }
+
+        unsigned char const *bytes = static_cast<unsigned char const *>(object);
+        std::ostringstream os;
+        os << "0x" << std::setfill('0') << std::hex;
+        for( ; i != end; i += inc )
+             os << std::setw(2) << static_cast<unsigned>(bytes[i]);
+       return os.str();
+    }
+}
+
+std::string toString( std::string const& value ) {
+    std::string s = value;
+    if( getCurrentContext().getConfig()->showInvisibles() ) {
+        for(size_t i = 0; i < s.size(); ++i ) {
+            std::string subs;
+            switch( s[i] ) {
+            case '\n': subs = "\\n"; break;
+            case '\t': subs = "\\t"; break;
+            default: break;
+            }
+            if( !subs.empty() ) {
+                s = s.substr( 0, i ) + subs + s.substr( i+1 );
+                ++i;
+            }
+        }
+    }
+    return '"' + s + '"';
+}
+std::string toString( std::wstring const& value ) {
+
+    std::string s;
+    s.reserve( value.size() );
+    for(size_t i = 0; i < value.size(); ++i )
+        s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
+    return Catch::toString( s );
+}
+
+std::string toString( const char* const value ) {
+    return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
+}
+
+std::string toString( char* const value ) {
+    return Catch::toString( static_cast<const char*>( value ) );
+}
+
+std::string toString( const wchar_t* const value )
+{
+    return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
+}
+
+std::string toString( wchar_t* const value )
+{
+    return Catch::toString( static_cast<const wchar_t*>( value ) );
+}
+
+std::string toString( int value ) {
+    std::ostringstream oss;
+    oss << value;
+    if( value > Detail::hexThreshold )
+        oss << " (0x" << std::hex << value << ')';
+    return oss.str();
+}
+
+std::string toString( unsigned long value ) {
+    std::ostringstream oss;
+    oss << value;
+    if( value > Detail::hexThreshold )
+        oss << " (0x" << std::hex << value << ')';
+    return oss.str();
+}
+
+std::string toString( unsigned int value ) {
+    return Catch::toString( static_cast<unsigned long>( value ) );
+}
+
+template<typename T>
+std::string fpToString( T value, int precision ) {
+    std::ostringstream oss;
+    oss << std::setprecision( precision )
+        << std::fixed
+        << value;
+    std::string d = oss.str();
+    std::size_t i = d.find_last_not_of( '0' );
+    if( i != std::string::npos && i != d.size()-1 ) {
+        if( d[i] == '.' )
+            i++;
+        d = d.substr( 0, i+1 );
+    }
+    return d;
+}
+
+std::string toString( const double value ) {
+    return fpToString( value, 10 );
+}
+std::string toString( const float value ) {
+    return fpToString( value, 5 ) + 'f';
+}
+
+std::string toString( bool value ) {
+    return value ? "true" : "false";
+}
+
+std::string toString( char value ) {
+    if ( value == '\r' )
+        return "'\\r'";
+    if ( value == '\f' )
+        return "'\\f'";
+    if ( value == '\n' )
+        return "'\\n'";
+    if ( value == '\t' )
+        return "'\\t'";
+    if ( '\0' <= value && value < ' ' )
+        return toString( static_cast<unsigned int>( value ) );
+    char chstr[] = "' '";
+    chstr[1] = value;
+    return chstr;
+}
+
+std::string toString( signed char value ) {
+    return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+    return toString( static_cast<char>( value ) );
+}
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value ) {
+    std::ostringstream oss;
+    oss << value;
+    if( value > Detail::hexThreshold )
+        oss << " (0x" << std::hex << value << ')';
+    return oss.str();
+}
+std::string toString( unsigned long long value ) {
+    std::ostringstream oss;
+    oss << value;
+    if( value > Detail::hexThreshold )
+        oss << " (0x" << std::hex << value << ')';
+    return oss.str();
+}
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t ) {
+    return "nullptr";
+}
+#endif
+
+#ifdef __OBJC__
+    std::string toString( NSString const * const& nsstring ) {
+        if( !nsstring )
+            return "nil";
+        return "@" + toString([nsstring UTF8String]);
+    }
+    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
+        if( !nsstring )
+            return "nil";
+        return "@" + toString([nsstring UTF8String]);
+    }
+    std::string toString( NSObject* const& nsObject ) {
+        return toString( [nsObject description] );
+    }
+#endif
+
+} // end namespace Catch
+
+// #included from: catch_result_builder.hpp
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
+
+namespace Catch {
+
+    std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
+        return secondArg.empty() || secondArg == "\"\""
+            ? capturedExpression
+            : capturedExpression + ", " + secondArg;
+    }
+    ResultBuilder::ResultBuilder(   char const* macroName,
+                                    SourceLineInfo const& lineInfo,
+                                    char const* capturedExpression,
+                                    ResultDisposition::Flags resultDisposition,
+                                    char const* secondArg )
+    :   m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
+        m_shouldDebugBreak( false ),
+        m_shouldThrow( false ),
+        m_guardException( false )
+    {}
+
+    ResultBuilder::~ResultBuilder() {
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+        if ( m_guardException ) {
+            m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
+            captureResult( ResultWas::ThrewException );
+            getCurrentContext().getResultCapture()->exceptionEarlyReported();
+        }
+#endif
+    }
+
+    ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
+        m_data.resultType = result;
+        return *this;
+    }
+    ResultBuilder& ResultBuilder::setResultType( bool result ) {
+        m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
+        return *this;
+    }
+
+    void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
+        AssertionResult result = build( expr );
+        handleResult( result );
+    }
+
+    void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
+        m_assertionInfo.resultDisposition = resultDisposition;
+        m_stream.oss << Catch::translateActiveException();
+        captureResult( ResultWas::ThrewException );
+    }
+
+    void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
+        setResultType( resultType );
+        captureExpression();
+    }
+
+    void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
+        if( expectedMessage.empty() )
+            captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
+        else
+            captureExpectedException( Matchers::Equals( expectedMessage ) );
+    }
+
+    void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
+
+        assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
+        AssertionResultData data = m_data;
+        data.resultType = ResultWas::Ok;
+        data.reconstructedExpression = m_assertionInfo.capturedExpression;
+
+        std::string actualMessage = Catch::translateActiveException();
+        if( !matcher.match( actualMessage ) ) {
+            data.resultType = ResultWas::ExpressionFailed;
+            data.reconstructedExpression = actualMessage;
+        }
+        AssertionResult result( m_assertionInfo, data );
+        handleResult( result );
+    }
+
+    void ResultBuilder::captureExpression() {
+        AssertionResult result = build();
+        handleResult( result );
+    }
+
+    void ResultBuilder::handleResult( AssertionResult const& result )
+    {
+        getResultCapture().assertionEnded( result );
+
+        if( !result.isOk() ) {
+            if( getCurrentContext().getConfig()->shouldDebugBreak() )
+                m_shouldDebugBreak = true;
+            if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
+                m_shouldThrow = true;
+        }
+    }
+
+    void ResultBuilder::react() {
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+        if (m_shouldDebugBreak) {
+            ///////////////////////////////////////////////////////////////////
+            // To inspect the state during test, you need to go one level up the callstack
+            // To go back to the test and change execution, jump over the throw statement
+            ///////////////////////////////////////////////////////////////////
+            CATCH_BREAK_INTO_DEBUGGER();
+        }
+#endif
+        if( m_shouldThrow )
+            throw Catch::TestFailureException();
+    }
+
+    bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
+    bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
+
+    AssertionResult ResultBuilder::build() const
+    {
+        return build( *this );
+    }
+
+    // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
+    //         a temporary DecomposedExpression, which in turn holds references to
+    //         operands, possibly temporary as well.
+    //         It should immediately be passed to handleResult; if the expression
+    //         needs to be reported, its string expansion must be composed before
+    //         the temporaries are destroyed.
+    AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
+    {
+        assert( m_data.resultType != ResultWas::Unknown );
+        AssertionResultData data = m_data;
+
+        // Flip bool results if FalseTest flag is set
+        if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
+            data.negate( expr.isBinaryExpression() );
+        }
+
+        data.message = m_stream.oss.str();
+        data.decomposedExpression = &expr; // for lazy reconstruction
+        return AssertionResult( m_assertionInfo, data );
+    }
+
+    void ResultBuilder::reconstructExpression( std::string& dest ) const {
+        dest = m_assertionInfo.capturedExpression;
+    }
+
+    void ResultBuilder::setExceptionGuard() {
+        m_guardException = true;
+    }
+    void ResultBuilder::unsetExceptionGuard() {
+        m_guardException = false;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_tag_alias_registry.hpp
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
+
+namespace Catch {
+
+    TagAliasRegistry::~TagAliasRegistry() {}
+
+    Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
+        std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
+        if( it != m_registry.end() )
+            return it->second;
+        else
+            return Option<TagAlias>();
+    }
+
+    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
+        std::string expandedTestSpec = unexpandedTestSpec;
+        for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
+                it != itEnd;
+                ++it ) {
+            std::size_t pos = expandedTestSpec.find( it->first );
+            if( pos != std::string::npos ) {
+                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
+                                    it->second.tag +
+                                    expandedTestSpec.substr( pos + it->first.size() );
+            }
+        }
+        return expandedTestSpec;
+    }
+
+    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
+
+        if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
+            std::ostringstream oss;
+            oss << Colour( Colour::Red )
+                << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n"
+                << Colour( Colour::FileName )
+                << lineInfo << '\n';
+            throw std::domain_error( oss.str().c_str() );
+        }
+        if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
+            std::ostringstream oss;
+            oss << Colour( Colour::Red )
+                << "error: tag alias, \"" << alias << "\" already registered.\n"
+                << "\tFirst seen at "
+                << Colour( Colour::Red ) << find(alias)->lineInfo << '\n'
+                << Colour( Colour::Red ) << "\tRedefined at "
+                << Colour( Colour::FileName) << lineInfo << '\n';
+            throw std::domain_error( oss.str().c_str() );
+        }
+    }
+
+    ITagAliasRegistry::~ITagAliasRegistry() {}
+
+    ITagAliasRegistry const& ITagAliasRegistry::get() {
+        return getRegistryHub().getTagAliasRegistry();
+    }
+
+    RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
+        getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo );
+    }
+
+} // end namespace Catch
+
+// #included from: catch_matchers_string.hpp
+
+namespace Catch {
+namespace Matchers {
+
+    namespace StdString {
+
+        CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
+        :   m_caseSensitivity( caseSensitivity ),
+            m_str( adjustString( str ) )
+        {}
+        std::string CasedString::adjustString( std::string const& str ) const {
+            return m_caseSensitivity == CaseSensitive::No
+                   ? toLower( str )
+                   : str;
+        }
+        std::string CasedString::caseSensitivitySuffix() const {
+            return m_caseSensitivity == CaseSensitive::No
+                   ? " (case insensitive)"
+                   : std::string();
+        }
+
+        StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
+        : m_comparator( comparator ),
+          m_operation( operation ) {
+        }
+
+        std::string StringMatcherBase::describe() const {
+            std::string description;
+            description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
+                                        m_comparator.caseSensitivitySuffix().size());
+            description += m_operation;
+            description += ": \"";
+            description += m_comparator.m_str;
+            description += "\"";
+            description += m_comparator.caseSensitivitySuffix();
+            return description;
+        }
+
+        EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
+
+        bool EqualsMatcher::match( std::string const& source ) const {
+            return m_comparator.adjustString( source ) == m_comparator.m_str;
+        }
+
+        ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
+
+        bool ContainsMatcher::match( std::string const& source ) const {
+            return contains( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+        StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
+
+        bool StartsWithMatcher::match( std::string const& source ) const {
+            return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+        EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
+
+        bool EndsWithMatcher::match( std::string const& source ) const {
+            return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+    } // namespace StdString
+
+    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+
+} // namespace Matchers
+} // namespace Catch
+// #included from: ../reporters/catch_reporter_multi.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
+
+namespace Catch {
+
+class MultipleReporters : public SharedImpl<IStreamingReporter> {
+    typedef std::vector<Ptr<IStreamingReporter> > Reporters;
+    Reporters m_reporters;
+
+public:
+    void add( Ptr<IStreamingReporter> const& reporter ) {
+        m_reporters.push_back( reporter );
+    }
+
+public: // IStreamingReporter
+
+    virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+        return m_reporters[0]->getPreferences();
+    }
+
+    virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->noMatchingTestCases( spec );
+    }
+
+    virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testRunStarting( testRunInfo );
+    }
+
+    virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testGroupStarting( groupInfo );
+    }
+
+    virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testCaseStarting( testInfo );
+    }
+
+    virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->sectionStarting( sectionInfo );
+    }
+
+    virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->assertionStarting( assertionInfo );
+    }
+
+    // The return value indicates if the messages buffer should be cleared:
+    virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+        bool clearBuffer = false;
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            clearBuffer |= (*it)->assertionEnded( assertionStats );
+        return clearBuffer;
+    }
+
+    virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->sectionEnded( sectionStats );
+    }
+
+    virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testCaseEnded( testCaseStats );
+    }
+
+    virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testGroupEnded( testGroupStats );
+    }
+
+    virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->testRunEnded( testRunStats );
+    }
+
+    virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+        for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+                it != itEnd;
+                ++it )
+            (*it)->skipTest( testInfo );
+    }
+
+    virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
+        return this;
+    }
+
+};
+
+Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
+    Ptr<IStreamingReporter> resultingReporter;
+
+    if( existingReporter ) {
+        MultipleReporters* multi = existingReporter->tryAsMulti();
+        if( !multi ) {
+            multi = new MultipleReporters;
+            resultingReporter = Ptr<IStreamingReporter>( multi );
+            if( existingReporter )
+                multi->add( existingReporter );
+        }
+        else
+            resultingReporter = existingReporter;
+        multi->add( additionalReporter );
+    }
+    else
+        resultingReporter = additionalReporter;
+
+    return resultingReporter;
+}
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_xml.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+
+// #included from: catch_reporter_bases.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
+
+#include <cstring>
+#include <cfloat>
+#include <cstdio>
+#include <assert.h>
+
+namespace Catch {
+
+    namespace {
+        // Because formatting using c++ streams is stateful, drop down to C is required
+        // Alternatively we could use stringstream, but its performance is... not good.
+        std::string getFormattedDuration( double duration ) {
+            // Max exponent + 1 is required to represent the whole part
+            // + 1 for decimal point
+            // + 3 for the 3 decimal places
+            // + 1 for null terminator
+            const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
+            char buffer[maxDoubleSize];
+
+            // Save previous errno, to prevent sprintf from overwriting it
+            ErrnoGuard guard;
+#ifdef _MSC_VER
+            sprintf_s(buffer, "%.3f", duration);
+#else
+            sprintf(buffer, "%.3f", duration);
+#endif
+            return std::string(buffer);
+        }
+    }
+
+    struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
+
+        StreamingReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = false;
+        }
+
+        virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+            return m_reporterPrefs;
+        }
+
+        virtual ~StreamingReporterBase() CATCH_OVERRIDE;
+
+        virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
+
+        virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
+            currentTestRunInfo = _testRunInfo;
+        }
+        virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
+            currentGroupInfo = _groupInfo;
+        }
+
+        virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
+            currentTestCaseInfo = _testInfo;
+        }
+        virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
+            m_sectionStack.push_back( _sectionInfo );
+        }
+
+        virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
+            m_sectionStack.pop_back();
+        }
+        virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
+            currentTestCaseInfo.reset();
+        }
+        virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
+            currentGroupInfo.reset();
+        }
+        virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
+            currentTestCaseInfo.reset();
+            currentGroupInfo.reset();
+            currentTestRunInfo.reset();
+        }
+
+        virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
+            // Don't do anything with this by default.
+            // It can optionally be overridden in the derived class.
+        }
+
+        Ptr<IConfig const> m_config;
+        std::ostream& stream;
+
+        LazyStat<TestRunInfo> currentTestRunInfo;
+        LazyStat<GroupInfo> currentGroupInfo;
+        LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+        std::vector<SectionInfo> m_sectionStack;
+        ReporterPreferences m_reporterPrefs;
+    };
+
+    struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+        template<typename T, typename ChildNodeT>
+        struct Node : SharedImpl<> {
+            explicit Node( T const& _value ) : value( _value ) {}
+            virtual ~Node() {}
+
+            typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
+            T value;
+            ChildNodes children;
+        };
+        struct SectionNode : SharedImpl<> {
+            explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
+            virtual ~SectionNode();
+
+            bool operator == ( SectionNode const& other ) const {
+                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+            }
+            bool operator == ( Ptr<SectionNode> const& other ) const {
+                return operator==( *other );
+            }
+
+            SectionStats stats;
+            typedef std::vector<Ptr<SectionNode> > ChildSections;
+            typedef std::vector<AssertionStats> Assertions;
+            ChildSections childSections;
+            Assertions assertions;
+            std::string stdOut;
+            std::string stdErr;
+        };
+
+        struct BySectionInfo {
+            BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+            BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
+            bool operator() ( Ptr<SectionNode> const& node ) const {
+                return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+            }
+        private:
+            void operator=( BySectionInfo const& );
+            SectionInfo const& m_other;
+        };
+
+        typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+        typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+        typedef Node<TestRunStats, TestGroupNode> TestRunNode;
+
+        CumulativeReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = false;
+        }
+        ~CumulativeReporterBase();
+
+        virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+            return m_reporterPrefs;
+        }
+
+        virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
+        virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
+
+        virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
+
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+            SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+            Ptr<SectionNode> node;
+            if( m_sectionStack.empty() ) {
+                if( !m_rootSection )
+                    m_rootSection = new SectionNode( incompleteStats );
+                node = m_rootSection;
+            }
+            else {
+                SectionNode& parentNode = *m_sectionStack.back();
+                SectionNode::ChildSections::const_iterator it =
+                    std::find_if(   parentNode.childSections.begin(),
+                                    parentNode.childSections.end(),
+                                    BySectionInfo( sectionInfo ) );
+                if( it == parentNode.childSections.end() ) {
+                    node = new SectionNode( incompleteStats );
+                    parentNode.childSections.push_back( node );
+                }
+                else
+                    node = *it;
+            }
+            m_sectionStack.push_back( node );
+            m_deepestSection = node;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
+
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+            assert( !m_sectionStack.empty() );
+            SectionNode& sectionNode = *m_sectionStack.back();
+            sectionNode.assertions.push_back( assertionStats );
+            // AssertionResult holds a pointer to a temporary DecomposedExpression,
+            // which getExpandedExpression() calls to build the expression string.
+            // Our section stack copy of the assertionResult will likely outlive the
+            // temporary, so it must be expanded or discarded now to avoid calling
+            // a destroyed object later.
+            prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
+            return true;
+        }
+        virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+            assert( !m_sectionStack.empty() );
+            SectionNode& node = *m_sectionStack.back();
+            node.stats = sectionStats;
+            m_sectionStack.pop_back();
+        }
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+            Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
+            assert( m_sectionStack.size() == 0 );
+            node->children.push_back( m_rootSection );
+            m_testCases.push_back( node );
+            m_rootSection.reset();
+
+            assert( m_deepestSection );
+            m_deepestSection->stdOut = testCaseStats.stdOut;
+            m_deepestSection->stdErr = testCaseStats.stdErr;
+        }
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+            Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
+            node->children.swap( m_testCases );
+            m_testGroups.push_back( node );
+        }
+        virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+            Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+            node->children.swap( m_testGroups );
+            m_testRuns.push_back( node );
+            testRunEndedCumulative();
+        }
+        virtual void testRunEndedCumulative() = 0;
+
+        virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
+
+        virtual void prepareExpandedExpression( AssertionResult& result ) const {
+            if( result.isOk() )
+                result.discardDecomposedExpression();
+            else
+                result.expandDecomposedExpression();
+        }
+
+        Ptr<IConfig const> m_config;
+        std::ostream& stream;
+        std::vector<AssertionStats> m_assertions;
+        std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+        std::vector<Ptr<TestCaseNode> > m_testCases;
+        std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+        std::vector<Ptr<TestRunNode> > m_testRuns;
+
+        Ptr<SectionNode> m_rootSection;
+        Ptr<SectionNode> m_deepestSection;
+        std::vector<Ptr<SectionNode> > m_sectionStack;
+        ReporterPreferences m_reporterPrefs;
+
+    };
+
+    template<char C>
+    char const* getLineOfChars() {
+        static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
+        if( !*line ) {
+            std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
+            line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
+        }
+        return line;
+    }
+
+    struct TestEventListenerBase : StreamingReporterBase {
+        TestEventListenerBase( ReporterConfig const& _config )
+        :   StreamingReporterBase( _config )
+        {}
+
+        virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
+        virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
+            return false;
+        }
+    };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+    template<typename T>
+    class LegacyReporterRegistrar {
+
+        class ReporterFactory : public IReporterFactory {
+            virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+                return new LegacyReporterAdapter( new T( config ) );
+            }
+
+            virtual std::string getDescription() const {
+                return T::getDescription();
+            }
+        };
+
+    public:
+
+        LegacyReporterRegistrar( std::string const& name ) {
+            getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+        }
+    };
+
+    template<typename T>
+    class ReporterRegistrar {
+
+        class ReporterFactory : public SharedImpl<IReporterFactory> {
+
+            // *** Please Note ***:
+            // - If you end up here looking at a compiler error because it's trying to register
+            // your custom reporter class be aware that the native reporter interface has changed
+            // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
+            // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
+            // However please consider updating to the new interface as the old one is now
+            // deprecated and will probably be removed quite soon!
+            // Please contact me via github if you have any questions at all about this.
+            // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
+            // no idea who is actually using custom reporters at all (possibly no-one!).
+            // The new interface is designed to minimise exposure to interface changes in the future.
+            virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+                return new T( config );
+            }
+
+            virtual std::string getDescription() const {
+                return T::getDescription();
+            }
+        };
+
+    public:
+
+        ReporterRegistrar( std::string const& name ) {
+            getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+        }
+    };
+
+    template<typename T>
+    class ListenerRegistrar {
+
+        class ListenerFactory : public SharedImpl<IReporterFactory> {
+
+            virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+                return new T( config );
+            }
+            virtual std::string getDescription() const {
+                return std::string();
+            }
+        };
+
+    public:
+
+        ListenerRegistrar() {
+            getMutableRegistryHub().registerListener( new ListenerFactory() );
+        }
+    };
+}
+
+#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
+    namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+    namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+// Deprecated - use the form without INTERNAL_
+#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
+    namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
+
+#define CATCH_REGISTER_LISTENER( listenerType ) \
+    namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include <iomanip>
+
+namespace Catch {
+
+    class XmlEncode {
+    public:
+        enum ForWhat { ForTextNodes, ForAttributes };
+
+        XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
+        :   m_str( str ),
+            m_forWhat( forWhat )
+        {}
+
+        void encodeTo( std::ostream& os ) const {
+
+            // Apostrophe escaping not necessary if we always use " to write attributes
+            // (see: http://www.w3.org/TR/xml/#syntax)
+
+            for( std::size_t i = 0; i < m_str.size(); ++ i ) {
+                char c = m_str[i];
+                switch( c ) {
+                    case '<':   os << "&lt;"; break;
+                    case '&':   os << "&amp;"; break;
+
+                    case '>':
+                        // See: http://www.w3.org/TR/xml/#syntax
+                        if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
+                            os << "&gt;";
+                        else
+                            os << c;
+                        break;
+
+                    case '\"':
+                        if( m_forWhat == ForAttributes )
+                            os << "&quot;";
+                        else
+                            os << c;
+                        break;
+
+                    default:
+                        // Escape control chars - based on contribution by @espenalb in PR #465 and
+                        // by @mrpi PR #588
+                        if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
+                            // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+                            os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+                               << static_cast<int>( c );
+                        }
+                        else
+                            os << c;
+                }
+            }
+        }
+
+        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+            xmlEncode.encodeTo( os );
+            return os;
+        }
+
+    private:
+        std::string m_str;
+        ForWhat m_forWhat;
+    };
+
+    class XmlWriter {
+    public:
+
+        class ScopedElement {
+        public:
+            ScopedElement( XmlWriter* writer )
+            :   m_writer( writer )
+            {}
+
+            ScopedElement( ScopedElement const& other )
+            :   m_writer( other.m_writer ){
+                other.m_writer = CATCH_NULL;
+            }
+
+            ~ScopedElement() {
+                if( m_writer )
+                    m_writer->endElement();
+            }
+
+            ScopedElement& writeText( std::string const& text, bool indent = true ) {
+                m_writer->writeText( text, indent );
+                return *this;
+            }
+
+            template<typename T>
+            ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+                m_writer->writeAttribute( name, attribute );
+                return *this;
+            }
+
+        private:
+            mutable XmlWriter* m_writer;
+        };
+
+        XmlWriter()
+        :   m_tagIsOpen( false ),
+            m_needsNewline( false ),
+            m_os( Catch::cout() )
+        {
+            writeDeclaration();
+        }
+
+        XmlWriter( std::ostream& os )
+        :   m_tagIsOpen( false ),
+            m_needsNewline( false ),
+            m_os( os )
+        {
+            writeDeclaration();
+        }
+
+        ~XmlWriter() {
+            while( !m_tags.empty() )
+                endElement();
+        }
+
+        XmlWriter& startElement( std::string const& name ) {
+            ensureTagClosed();
+            newlineIfNecessary();
+            m_os << m_indent << '<' << name;
+            m_tags.push_back( name );
+            m_indent += "  ";
+            m_tagIsOpen = true;
+            return *this;
+        }
+
+        ScopedElement scopedElement( std::string const& name ) {
+            ScopedElement scoped( this );
+            startElement( name );
+            return scoped;
+        }
+
+        XmlWriter& endElement() {
+            newlineIfNecessary();
+            m_indent = m_indent.substr( 0, m_indent.size()-2 );
+            if( m_tagIsOpen ) {
+                m_os << "/>";
+                m_tagIsOpen = false;
+            }
+            else {
+                m_os << m_indent << "</" << m_tags.back() << ">";
+            }
+            m_os << std::endl;
+            m_tags.pop_back();
+            return *this;
+        }
+
+        XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
+            if( !name.empty() && !attribute.empty() )
+                m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+            return *this;
+        }
+
+        XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
+            m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
+            return *this;
+        }
+
+        template<typename T>
+        XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+            std::ostringstream oss;
+            oss << attribute;
+            return writeAttribute( name, oss.str() );
+        }
+
+        XmlWriter& writeText( std::string const& text, bool indent = true ) {
+            if( !text.empty() ){
+                bool tagWasOpen = m_tagIsOpen;
+                ensureTagClosed();
+                if( tagWasOpen && indent )
+                    m_os << m_indent;
+                m_os << XmlEncode( text );
+                m_needsNewline = true;
+            }
+            return *this;
+        }
+
+        XmlWriter& writeComment( std::string const& text ) {
+            ensureTagClosed();
+            m_os << m_indent << "<!--" << text << "-->";
+            m_needsNewline = true;
+            return *this;
+        }
+
+        void writeStylesheetRef( std::string const& url ) {
+            m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
+        }
+
+        XmlWriter& writeBlankLine() {
+            ensureTagClosed();
+            m_os << '\n';
+            return *this;
+        }
+
+        void ensureTagClosed() {
+            if( m_tagIsOpen ) {
+                m_os << ">" << std::endl;
+                m_tagIsOpen = false;
+            }
+        }
+
+    private:
+        XmlWriter( XmlWriter const& );
+        void operator=( XmlWriter const& );
+
+        void writeDeclaration() {
+            m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+        }
+
+        void newlineIfNecessary() {
+            if( m_needsNewline ) {
+                m_os << std::endl;
+                m_needsNewline = false;
+            }
+        }
+
+        bool m_tagIsOpen;
+        bool m_needsNewline;
+        std::vector<std::string> m_tags;
+        std::string m_indent;
+        std::ostream& m_os;
+    };
+
+}
+// #included from: catch_reenable_warnings.h
+
+#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
+
+#ifdef __clang__
+#    ifdef __ICC // icpc defines the __clang__ macro
+#        pragma warning(pop)
+#    else
+#        pragma clang diagnostic pop
+#    endif
+#elif defined __GNUC__
+#    pragma GCC diagnostic pop
+#endif
+
+
+namespace Catch {
+    class XmlReporter : public StreamingReporterBase {
+    public:
+        XmlReporter( ReporterConfig const& _config )
+        :   StreamingReporterBase( _config ),
+            m_xml(_config.stream()),
+            m_sectionDepth( 0 )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = true;
+        }
+
+        virtual ~XmlReporter() CATCH_OVERRIDE;
+
+        static std::string getDescription() {
+            return "Reports test results as an XML document";
+        }
+
+        virtual std::string getStylesheetRef() const {
+            return std::string();
+        }
+
+        void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
+            m_xml
+                .writeAttribute( "filename", sourceInfo.file )
+                .writeAttribute( "line", sourceInfo.line );
+        }
+
+    public: // StreamingReporterBase
+
+        virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
+            StreamingReporterBase::noMatchingTestCases( s );
+        }
+
+        virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
+            StreamingReporterBase::testRunStarting( testInfo );
+            std::string stylesheetRef = getStylesheetRef();
+            if( !stylesheetRef.empty() )
+                m_xml.writeStylesheetRef( stylesheetRef );
+            m_xml.startElement( "Catch" );
+            if( !m_config->name().empty() )
+                m_xml.writeAttribute( "name", m_config->name() );
+        }
+
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+            StreamingReporterBase::testGroupStarting( groupInfo );
+            m_xml.startElement( "Group" )
+                .writeAttribute( "name", groupInfo.name );
+        }
+
+        virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+            StreamingReporterBase::testCaseStarting(testInfo);
+            m_xml.startElement( "TestCase" )
+                .writeAttribute( "name", trim( testInfo.name ) )
+                .writeAttribute( "description", testInfo.description )
+                .writeAttribute( "tags", testInfo.tagsAsString );
+
+            writeSourceInfo( testInfo.lineInfo );
+
+            if ( m_config->showDurations() == ShowDurations::Always )
+                m_testCaseTimer.start();
+            m_xml.ensureTagClosed();
+        }
+
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+            StreamingReporterBase::sectionStarting( sectionInfo );
+            if( m_sectionDepth++ > 0 ) {
+                m_xml.startElement( "Section" )
+                    .writeAttribute( "name", trim( sectionInfo.name ) )
+                    .writeAttribute( "description", sectionInfo.description );
+                writeSourceInfo( sectionInfo.lineInfo );
+                m_xml.ensureTagClosed();
+            }
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
+
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+
+            AssertionResult const& result = assertionStats.assertionResult;
+
+            bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
+
+            if( includeResults ) {
+                // Print any info messages in <Info> tags.
+                for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
+                     it != itEnd;
+                     ++it ) {
+                    if( it->type == ResultWas::Info ) {
+                        m_xml.scopedElement( "Info" )
+                                .writeText( it->message );
+                    } else if ( it->type == ResultWas::Warning ) {
+                        m_xml.scopedElement( "Warning" )
+                                .writeText( it->message );
+                    }
+                }
+            }
+
+            // Drop out if result was successful but we're not printing them.
+            if( !includeResults && result.getResultType() != ResultWas::Warning )
+                return true;
+
+            // Print the expression if there is one.
+            if( result.hasExpression() ) {
+                m_xml.startElement( "Expression" )
+                    .writeAttribute( "success", result.succeeded() )
+                    .writeAttribute( "type", result.getTestMacroName() );
+
+                writeSourceInfo( result.getSourceInfo() );
+
+                m_xml.scopedElement( "Original" )
+                    .writeText( result.getExpression() );
+                m_xml.scopedElement( "Expanded" )
+                    .writeText( result.getExpandedExpression() );
+            }
+
+            // And... Print a result applicable to each result type.
+            switch( result.getResultType() ) {
+                case ResultWas::ThrewException:
+                    m_xml.startElement( "Exception" );
+                    writeSourceInfo( result.getSourceInfo() );
+                    m_xml.writeText( result.getMessage() );
+                    m_xml.endElement();
+                    break;
+                case ResultWas::FatalErrorCondition:
+                    m_xml.startElement( "FatalErrorCondition" );
+                    writeSourceInfo( result.getSourceInfo() );
+                    m_xml.writeText( result.getMessage() );
+                    m_xml.endElement();
+                    break;
+                case ResultWas::Info:
+                    m_xml.scopedElement( "Info" )
+                        .writeText( result.getMessage() );
+                    break;
+                case ResultWas::Warning:
+                    // Warning will already have been written
+                    break;
+                case ResultWas::ExplicitFailure:
+                    m_xml.startElement( "Failure" );
+                    writeSourceInfo( result.getSourceInfo() );
+                    m_xml.writeText( result.getMessage() );
+                    m_xml.endElement();
+                    break;
+                default:
+                    break;
+            }
+
+            if( result.hasExpression() )
+                m_xml.endElement();
+
+            return true;
+        }
+
+        virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+            StreamingReporterBase::sectionEnded( sectionStats );
+            if( --m_sectionDepth > 0 ) {
+                XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
+                e.writeAttribute( "successes", sectionStats.assertions.passed );
+                e.writeAttribute( "failures", sectionStats.assertions.failed );
+                e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
+
+                if ( m_config->showDurations() == ShowDurations::Always )
+                    e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
+
+                m_xml.endElement();
+            }
+        }
+
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+            StreamingReporterBase::testCaseEnded( testCaseStats );
+            XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
+            e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
+
+            if ( m_config->showDurations() == ShowDurations::Always )
+                e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
+
+            if( !testCaseStats.stdOut.empty() )
+                m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
+            if( !testCaseStats.stdErr.empty() )
+                m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
+
+            m_xml.endElement();
+        }
+
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+            StreamingReporterBase::testGroupEnded( testGroupStats );
+            // TODO: Check testGroupStats.aborting and act accordingly.
+            m_xml.scopedElement( "OverallResults" )
+                .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
+                .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
+                .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
+            m_xml.endElement();
+        }
+
+        virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+            StreamingReporterBase::testRunEnded( testRunStats );
+            m_xml.scopedElement( "OverallResults" )
+                .writeAttribute( "successes", testRunStats.totals.assertions.passed )
+                .writeAttribute( "failures", testRunStats.totals.assertions.failed )
+                .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
+            m_xml.endElement();
+        }
+
+    private:
+        Timer m_testCaseTimer;
+        XmlWriter m_xml;
+        int m_sectionDepth;
+    };
+
+     INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_junit.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
+
+#include <assert.h>
+
+namespace Catch {
+
+    namespace {
+        std::string getCurrentTimestamp() {
+            // Beware, this is not reentrant because of backward compatibility issues
+            // Also, UTC only, again because of backward compatibility (%z is C++11)
+            time_t rawtime;
+            std::time(&rawtime);
+            const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
+
+#ifdef _MSC_VER
+            std::tm timeInfo = {};
+            gmtime_s(&timeInfo, &rawtime);
+#else
+            std::tm* timeInfo;
+            timeInfo = std::gmtime(&rawtime);
+#endif
+
+            char timeStamp[timeStampSize];
+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+            return std::string(timeStamp);
+        }
+
+    }
+
+    class JunitReporter : public CumulativeReporterBase {
+    public:
+        JunitReporter( ReporterConfig const& _config )
+        :   CumulativeReporterBase( _config ),
+            xml( _config.stream() ),
+            m_okToFail( false )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = true;
+        }
+
+        virtual ~JunitReporter() CATCH_OVERRIDE;
+
+        static std::string getDescription() {
+            return "Reports test results in an XML format that looks like Ant's junitreport target";
+        }
+
+        virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
+
+        virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
+            CumulativeReporterBase::testRunStarting( runInfo );
+            xml.startElement( "testsuites" );
+        }
+
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+            suiteTimer.start();
+            stdOutForSuite.str("");
+            stdErrForSuite.str("");
+            unexpectedExceptions = 0;
+            CumulativeReporterBase::testGroupStarting( groupInfo );
+        }
+
+        virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE {
+            m_okToFail = testCaseInfo.okToFail();
+        }
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+            if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
+                unexpectedExceptions++;
+            return CumulativeReporterBase::assertionEnded( assertionStats );
+        }
+
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+            stdOutForSuite << testCaseStats.stdOut;
+            stdErrForSuite << testCaseStats.stdErr;
+            CumulativeReporterBase::testCaseEnded( testCaseStats );
+        }
+
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+            double suiteTime = suiteTimer.getElapsedSeconds();
+            CumulativeReporterBase::testGroupEnded( testGroupStats );
+            writeGroup( *m_testGroups.back(), suiteTime );
+        }
+
+        virtual void testRunEndedCumulative() CATCH_OVERRIDE {
+            xml.endElement();
+        }
+
+        void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
+            XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
+            TestGroupStats const& stats = groupNode.value;
+            xml.writeAttribute( "name", stats.groupInfo.name );
+            xml.writeAttribute( "errors", unexpectedExceptions );
+            xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
+            xml.writeAttribute( "tests", stats.totals.assertions.total() );
+            xml.writeAttribute( "hostname", "tbd" ); // !TBD
+            if( m_config->showDurations() == ShowDurations::Never )
+                xml.writeAttribute( "time", "" );
+            else
+                xml.writeAttribute( "time", suiteTime );
+            xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+
+            // Write test cases
+            for( TestGroupNode::ChildNodes::const_iterator
+                    it = groupNode.children.begin(), itEnd = groupNode.children.end();
+                    it != itEnd;
+                    ++it )
+                writeTestCase( **it );
+
+            xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
+            xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
+        }
+
+        void writeTestCase( TestCaseNode const& testCaseNode ) {
+            TestCaseStats const& stats = testCaseNode.value;
+
+            // All test cases have exactly one section - which represents the
+            // test case itself. That section may have 0-n nested sections
+            assert( testCaseNode.children.size() == 1 );
+            SectionNode const& rootSection = *testCaseNode.children.front();
+
+            std::string className = stats.testInfo.className;
+
+            if( className.empty() ) {
+                if( rootSection.childSections.empty() )
+                    className = "global";
+            }
+            writeSection( className, "", rootSection );
+        }
+
+        void writeSection(  std::string const& className,
+                            std::string const& rootName,
+                            SectionNode const& sectionNode ) {
+            std::string name = trim( sectionNode.stats.sectionInfo.name );
+            if( !rootName.empty() )
+                name = rootName + '/' + name;
+
+            if( !sectionNode.assertions.empty() ||
+                !sectionNode.stdOut.empty() ||
+                !sectionNode.stdErr.empty() ) {
+                XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
+                if( className.empty() ) {
+                    xml.writeAttribute( "classname", name );
+                    xml.writeAttribute( "name", "root" );
+                }
+                else {
+                    xml.writeAttribute( "classname", className );
+                    xml.writeAttribute( "name", name );
+                }
+                xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
+
+                writeAssertions( sectionNode );
+
+                if( !sectionNode.stdOut.empty() )
+                    xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
+                if( !sectionNode.stdErr.empty() )
+                    xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
+            }
+            for( SectionNode::ChildSections::const_iterator
+                    it = sectionNode.childSections.begin(),
+                    itEnd = sectionNode.childSections.end();
+                    it != itEnd;
+                    ++it )
+                if( className.empty() )
+                    writeSection( name, "", **it );
+                else
+                    writeSection( className, name, **it );
+        }
+
+        void writeAssertions( SectionNode const& sectionNode ) {
+            for( SectionNode::Assertions::const_iterator
+                    it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
+                    it != itEnd;
+                    ++it )
+                writeAssertion( *it );
+        }
+        void writeAssertion( AssertionStats const& stats ) {
+            AssertionResult const& result = stats.assertionResult;
+            if( !result.isOk() ) {
+                std::string elementName;
+                switch( result.getResultType() ) {
+                    case ResultWas::ThrewException:
+                    case ResultWas::FatalErrorCondition:
+                        elementName = "error";
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        elementName = "failure";
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        elementName = "failure";
+                        break;
+                    case ResultWas::DidntThrowException:
+                        elementName = "failure";
+                        break;
+
+                    // We should never see these here:
+                    case ResultWas::Info:
+                    case ResultWas::Warning:
+                    case ResultWas::Ok:
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        elementName = "internalError";
+                        break;
+                }
+
+                XmlWriter::ScopedElement e = xml.scopedElement( elementName );
+
+                xml.writeAttribute( "message", result.getExpandedExpression() );
+                xml.writeAttribute( "type", result.getTestMacroName() );
+
+                std::ostringstream oss;
+                if( !result.getMessage().empty() )
+                    oss << result.getMessage() << '\n';
+                for( std::vector<MessageInfo>::const_iterator
+                        it = stats.infoMessages.begin(),
+                        itEnd = stats.infoMessages.end();
+                            it != itEnd;
+                            ++it )
+                    if( it->type == ResultWas::Info )
+                        oss << it->message << '\n';
+
+                oss << "at " << result.getSourceInfo();
+                xml.writeText( oss.str(), false );
+            }
+        }
+
+        XmlWriter xml;
+        Timer suiteTimer;
+        std::ostringstream stdOutForSuite;
+        std::ostringstream stdErrForSuite;
+        unsigned int unexpectedExceptions;
+        bool m_okToFail;
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_console.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
+
+#include <cfloat>
+#include <cstdio>
+
+namespace Catch {
+
+    struct ConsoleReporter : StreamingReporterBase {
+        ConsoleReporter( ReporterConfig const& _config )
+        :   StreamingReporterBase( _config ),
+            m_headerPrinted( false )
+        {}
+
+        virtual ~ConsoleReporter() CATCH_OVERRIDE;
+        static std::string getDescription() {
+            return "Reports test results as plain lines of text";
+        }
+
+        virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
+            stream << "No test cases matched '" << spec << '\'' << std::endl;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
+        }
+
+        virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
+            AssertionResult const& result = _assertionStats.assertionResult;
+
+            bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
+
+            // Drop out if result was successful but we're not printing them.
+            if( !includeResults && result.getResultType() != ResultWas::Warning )
+                return false;
+
+            lazyPrint();
+
+            AssertionPrinter printer( stream, _assertionStats, includeResults );
+            printer.print();
+            stream << std::endl;
+            return true;
+        }
+
+        virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
+            m_headerPrinted = false;
+            StreamingReporterBase::sectionStarting( _sectionInfo );
+        }
+        virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
+            if( _sectionStats.missingAssertions ) {
+                lazyPrint();
+                Colour colour( Colour::ResultError );
+                if( m_sectionStack.size() > 1 )
+                    stream << "\nNo assertions in section";
+                else
+                    stream << "\nNo assertions in test case";
+                stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
+            }
+            if( m_config->showDurations() == ShowDurations::Always ) {
+                stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
+            }
+            if( m_headerPrinted ) {
+                m_headerPrinted = false;
+            }
+            StreamingReporterBase::sectionEnded( _sectionStats );
+        }
+
+        virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
+            StreamingReporterBase::testCaseEnded( _testCaseStats );
+            m_headerPrinted = false;
+        }
+        virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
+            if( currentGroupInfo.used ) {
+                printSummaryDivider();
+                stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
+                printTotals( _testGroupStats.totals );
+                stream << '\n' << std::endl;
+            }
+            StreamingReporterBase::testGroupEnded( _testGroupStats );
+        }
+        virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
+            printTotalsDivider( _testRunStats.totals );
+            printTotals( _testRunStats.totals );
+            stream << std::endl;
+            StreamingReporterBase::testRunEnded( _testRunStats );
+        }
+
+    private:
+
+        class AssertionPrinter {
+            void operator= ( AssertionPrinter const& );
+        public:
+            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+            :   stream( _stream ),
+                stats( _stats ),
+                result( _stats.assertionResult ),
+                colour( Colour::None ),
+                message( result.getMessage() ),
+                messages( _stats.infoMessages ),
+                printInfoMessages( _printInfoMessages )
+            {
+                switch( result.getResultType() ) {
+                    case ResultWas::Ok:
+                        colour = Colour::Success;
+                        passOrFail = "PASSED";
+                        //if( result.hasMessage() )
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "with messages";
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        if( result.isOk() ) {
+                            colour = Colour::Success;
+                            passOrFail = "FAILED - but was ok";
+                        }
+                        else {
+                            colour = Colour::Error;
+                            passOrFail = "FAILED";
+                        }
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "with messages";
+                        break;
+                    case ResultWas::ThrewException:
+                        colour = Colour::Error;
+                        passOrFail = "FAILED";
+                        messageLabel = "due to unexpected exception with ";
+                        if (_stats.infoMessages.size() == 1)
+                            messageLabel += "message";
+                        if (_stats.infoMessages.size() > 1)
+                            messageLabel += "messages";
+                        break;
+                    case ResultWas::FatalErrorCondition:
+                        colour = Colour::Error;
+                        passOrFail = "FAILED";
+                        messageLabel = "due to a fatal error condition";
+                        break;
+                    case ResultWas::DidntThrowException:
+                        colour = Colour::Error;
+                        passOrFail = "FAILED";
+                        messageLabel = "because no exception was thrown where one was expected";
+                        break;
+                    case ResultWas::Info:
+                        messageLabel = "info";
+                        break;
+                    case ResultWas::Warning:
+                        messageLabel = "warning";
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        passOrFail = "FAILED";
+                        colour = Colour::Error;
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "explicitly with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "explicitly with messages";
+                        break;
+                    // These cases are here to prevent compiler warnings
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        passOrFail = "** internal error **";
+                        colour = Colour::Error;
+                        break;
+                }
+            }
+
+            void print() const {
+                printSourceInfo();
+                if( stats.totals.assertions.total() > 0 ) {
+                    if( result.isOk() )
+                        stream << '\n';
+                    printResultType();
+                    printOriginalExpression();
+                    printReconstructedExpression();
+                }
+                else {
+                    stream << '\n';
+                }
+                printMessage();
+            }
+
+        private:
+            void printResultType() const {
+                if( !passOrFail.empty() ) {
+                    Colour colourGuard( colour );
+                    stream << passOrFail << ":\n";
+                }
+            }
+            void printOriginalExpression() const {
+                if( result.hasExpression() ) {
+                    Colour colourGuard( Colour::OriginalExpression );
+                    stream  << "  ";
+                    stream << result.getExpressionInMacro();
+                    stream << '\n';
+                }
+            }
+            void printReconstructedExpression() const {
+                if( result.hasExpandedExpression() ) {
+                    stream << "with expansion:\n";
+                    Colour colourGuard( Colour::ReconstructedExpression );
+                    stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
+                }
+            }
+            void printMessage() const {
+                if( !messageLabel.empty() )
+                    stream << messageLabel << ':' << '\n';
+                for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
+                        it != itEnd;
+                        ++it ) {
+                    // If this assertion is a warning ignore any INFO messages
+                    if( printInfoMessages || it->type != ResultWas::Info )
+                        stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
+                }
+            }
+            void printSourceInfo() const {
+                Colour colourGuard( Colour::FileName );
+                stream << result.getSourceInfo() << ": ";
+            }
+
+            std::ostream& stream;
+            AssertionStats const& stats;
+            AssertionResult const& result;
+            Colour::Code colour;
+            std::string passOrFail;
+            std::string messageLabel;
+            std::string message;
+            std::vector<MessageInfo> messages;
+            bool printInfoMessages;
+        };
+
+        void lazyPrint() {
+
+            if( !currentTestRunInfo.used )
+                lazyPrintRunInfo();
+            if( !currentGroupInfo.used )
+                lazyPrintGroupInfo();
+
+            if( !m_headerPrinted ) {
+                printTestCaseAndSectionHeader();
+                m_headerPrinted = true;
+            }
+        }
+        void lazyPrintRunInfo() {
+            stream  << '\n' << getLineOfChars<'~'>() << '\n';
+            Colour colour( Colour::SecondaryText );
+            stream  << currentTestRunInfo->name
+                    << " is a Catch v"  << libraryVersion() << " host application.\n"
+                    << "Run with -? for options\n\n";
+
+            if( m_config->rngSeed() != 0 )
+                stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
+
+            currentTestRunInfo.used = true;
+        }
+        void lazyPrintGroupInfo() {
+            if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
+                printClosedHeader( "Group: " + currentGroupInfo->name );
+                currentGroupInfo.used = true;
+            }
+        }
+        void printTestCaseAndSectionHeader() {
+            assert( !m_sectionStack.empty() );
+            printOpenHeader( currentTestCaseInfo->name );
+
+            if( m_sectionStack.size() > 1 ) {
+                Colour colourGuard( Colour::Headers );
+
+                std::vector<SectionInfo>::const_iterator
+                    it = m_sectionStack.begin()+1, // Skip first section (test case)
+                    itEnd = m_sectionStack.end();
+                for( ; it != itEnd; ++it )
+                    printHeaderString( it->name, 2 );
+            }
+
+            SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
+
+            if( !lineInfo.empty() ){
+                stream << getLineOfChars<'-'>() << '\n';
+                Colour colourGuard( Colour::FileName );
+                stream << lineInfo << '\n';
+            }
+            stream << getLineOfChars<'.'>() << '\n' << std::endl;
+        }
+
+        void printClosedHeader( std::string const& _name ) {
+            printOpenHeader( _name );
+            stream << getLineOfChars<'.'>() << '\n';
+        }
+        void printOpenHeader( std::string const& _name ) {
+            stream  << getLineOfChars<'-'>() << '\n';
+            {
+                Colour colourGuard( Colour::Headers );
+                printHeaderString( _name );
+            }
+        }
+
+        // if string has a : in first line will set indent to follow it on
+        // subsequent lines
+        void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
+            std::size_t i = _string.find( ": " );
+            if( i != std::string::npos )
+                i+=2;
+            else
+                i = 0;
+            stream << Text( _string, TextAttributes()
+                                        .setIndent( indent+i)
+                                        .setInitialIndent( indent ) ) << '\n';
+        }
+
+        struct SummaryColumn {
+
+            SummaryColumn( std::string const& _label, Colour::Code _colour )
+            :   label( _label ),
+                colour( _colour )
+            {}
+            SummaryColumn addRow( std::size_t count ) {
+                std::ostringstream oss;
+                oss << count;
+                std::string row = oss.str();
+                for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
+                    while( it->size() < row.size() )
+                        *it = ' ' + *it;
+                    while( it->size() > row.size() )
+                        row = ' ' + row;
+                }
+                rows.push_back( row );
+                return *this;
+            }
+
+            std::string label;
+            Colour::Code colour;
+            std::vector<std::string> rows;
+
+        };
+
+        void printTotals( Totals const& totals ) {
+            if( totals.testCases.total() == 0 ) {
+                stream << Colour( Colour::Warning ) << "No tests ran\n";
+            }
+            else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
+                stream << Colour( Colour::ResultSuccess ) << "All tests passed";
+                stream << " ("
+                        << pluralise( totals.assertions.passed, "assertion" ) << " in "
+                        << pluralise( totals.testCases.passed, "test case" ) << ')'
+                        << '\n';
+            }
+            else {
+
+                std::vector<SummaryColumn> columns;
+                columns.push_back( SummaryColumn( "", Colour::None )
+                                        .addRow( totals.testCases.total() )
+                                        .addRow( totals.assertions.total() ) );
+                columns.push_back( SummaryColumn( "passed", Colour::Success )
+                                        .addRow( totals.testCases.passed )
+                                        .addRow( totals.assertions.passed ) );
+                columns.push_back( SummaryColumn( "failed", Colour::ResultError )
+                                        .addRow( totals.testCases.failed )
+                                        .addRow( totals.assertions.failed ) );
+                columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
+                                        .addRow( totals.testCases.failedButOk )
+                                        .addRow( totals.assertions.failedButOk ) );
+
+                printSummaryRow( "test cases", columns, 0 );
+                printSummaryRow( "assertions", columns, 1 );
+            }
+        }
+        void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
+            for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
+                std::string value = it->rows[row];
+                if( it->label.empty() ) {
+                    stream << label << ": ";
+                    if( value != "0" )
+                        stream << value;
+                    else
+                        stream << Colour( Colour::Warning ) << "- none -";
+                }
+                else if( value != "0" ) {
+                    stream  << Colour( Colour::LightGrey ) << " | ";
+                    stream  << Colour( it->colour )
+                            << value << ' ' << it->label;
+                }
+            }
+            stream << '\n';
+        }
+
+        static std::size_t makeRatio( std::size_t number, std::size_t total ) {
+            std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
+            return ( ratio == 0 && number > 0 ) ? 1 : ratio;
+        }
+        static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
+            if( i > j && i > k )
+                return i;
+            else if( j > k )
+                return j;
+            else
+                return k;
+        }
+
+        void printTotalsDivider( Totals const& totals ) {
+            if( totals.testCases.total() > 0 ) {
+                std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
+                std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
+                std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
+                while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
+                    findMax( failedRatio, failedButOkRatio, passedRatio )++;
+                while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
+                    findMax( failedRatio, failedButOkRatio, passedRatio )--;
+
+                stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
+                stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
+                if( totals.testCases.allPassed() )
+                    stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
+                else
+                    stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
+            }
+            else {
+                stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
+            }
+            stream << '\n';
+        }
+        void printSummaryDivider() {
+            stream << getLineOfChars<'-'>() << '\n';
+        }
+
+    private:
+        bool m_headerPrinted;
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_compact.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
+
+namespace Catch {
+
+    struct CompactReporter : StreamingReporterBase {
+
+        CompactReporter( ReporterConfig const& _config )
+        : StreamingReporterBase( _config )
+        {}
+
+        virtual ~CompactReporter();
+
+        static std::string getDescription() {
+            return "Reports test results on a single line, suitable for IDEs";
+        }
+
+        virtual ReporterPreferences getPreferences() const {
+            ReporterPreferences prefs;
+            prefs.shouldRedirectStdOut = false;
+            return prefs;
+        }
+
+        virtual void noMatchingTestCases( std::string const& spec ) {
+            stream << "No test cases matched '" << spec << '\'' << std::endl;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) {}
+
+        virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+            AssertionResult const& result = _assertionStats.assertionResult;
+
+            bool printInfoMessages = true;
+
+            // Drop out if result was successful and we're not printing those
+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+                if( result.getResultType() != ResultWas::Warning )
+                    return false;
+                printInfoMessages = false;
+            }
+
+            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+            printer.print();
+
+            stream << std::endl;
+            return true;
+        }
+
+        virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
+            if (m_config->showDurations() == ShowDurations::Always) {
+                stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
+            }
+        }
+
+        virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+            printTotals( _testRunStats.totals );
+            stream << '\n' << std::endl;
+            StreamingReporterBase::testRunEnded( _testRunStats );
+        }
+
+    private:
+        class AssertionPrinter {
+            void operator= ( AssertionPrinter const& );
+        public:
+            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+            : stream( _stream )
+            , stats( _stats )
+            , result( _stats.assertionResult )
+            , messages( _stats.infoMessages )
+            , itMessage( _stats.infoMessages.begin() )
+            , printInfoMessages( _printInfoMessages )
+            {}
+
+            void print() {
+                printSourceInfo();
+
+                itMessage = messages.begin();
+
+                switch( result.getResultType() ) {
+                    case ResultWas::Ok:
+                        printResultType( Colour::ResultSuccess, passedString() );
+                        printOriginalExpression();
+                        printReconstructedExpression();
+                        if ( ! result.hasExpression() )
+                            printRemainingMessages( Colour::None );
+                        else
+                            printRemainingMessages();
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        if( result.isOk() )
+                            printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
+                        else
+                            printResultType( Colour::Error, failedString() );
+                        printOriginalExpression();
+                        printReconstructedExpression();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::ThrewException:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "unexpected exception with message:" );
+                        printMessage();
+                        printExpressionWas();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::FatalErrorCondition:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "fatal error condition with message:" );
+                        printMessage();
+                        printExpressionWas();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::DidntThrowException:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "expected exception, got none" );
+                        printExpressionWas();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::Info:
+                        printResultType( Colour::None, "info" );
+                        printMessage();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::Warning:
+                        printResultType( Colour::None, "warning" );
+                        printMessage();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "explicitly" );
+                        printRemainingMessages( Colour::None );
+                        break;
+                    // These cases are here to prevent compiler warnings
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        printResultType( Colour::Error, "** internal error **" );
+                        break;
+                }
+            }
+
+        private:
+            // Colour::LightGrey
+
+            static Colour::Code dimColour() { return Colour::FileName; }
+
+#ifdef CATCH_PLATFORM_MAC
+            static const char* failedString() { return "FAILED"; }
+            static const char* passedString() { return "PASSED"; }
+#else
+            static const char* failedString() { return "failed"; }
+            static const char* passedString() { return "passed"; }
+#endif
+
+            void printSourceInfo() const {
+                Colour colourGuard( Colour::FileName );
+                stream << result.getSourceInfo() << ':';
+            }
+
+            void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
+                if( !passOrFail.empty() ) {
+                    {
+                        Colour colourGuard( colour );
+                        stream << ' ' << passOrFail;
+                    }
+                    stream << ':';
+                }
+            }
+
+            void printIssue( std::string const& issue ) const {
+                stream << ' ' << issue;
+            }
+
+            void printExpressionWas() {
+                if( result.hasExpression() ) {
+                    stream << ';';
+                    {
+                        Colour colour( dimColour() );
+                        stream << " expression was:";
+                    }
+                    printOriginalExpression();
+                }
+            }
+
+            void printOriginalExpression() const {
+                if( result.hasExpression() ) {
+                    stream << ' ' << result.getExpression();
+                }
+            }
+
+            void printReconstructedExpression() const {
+                if( result.hasExpandedExpression() ) {
+                    {
+                        Colour colour( dimColour() );
+                        stream << " for: ";
+                    }
+                    stream << result.getExpandedExpression();
+                }
+            }
+
+            void printMessage() {
+                if ( itMessage != messages.end() ) {
+                    stream << " '" << itMessage->message << '\'';
+                    ++itMessage;
+                }
+            }
+
+            void printRemainingMessages( Colour::Code colour = dimColour() ) {
+                if ( itMessage == messages.end() )
+                    return;
+
+                // using messages.end() directly yields compilation error:
+                std::vector<MessageInfo>::const_iterator itEnd = messages.end();
+                const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
+
+                {
+                    Colour colourGuard( colour );
+                    stream << " with " << pluralise( N, "message" ) << ':';
+                }
+
+                for(; itMessage != itEnd; ) {
+                    // If this assertion is a warning ignore any INFO messages
+                    if( printInfoMessages || itMessage->type != ResultWas::Info ) {
+                        stream << " '" << itMessage->message << '\'';
+                        if ( ++itMessage != itEnd ) {
+                            Colour colourGuard( dimColour() );
+                            stream << " and";
+                        }
+                    }
+                }
+            }
+
+        private:
+            std::ostream& stream;
+            AssertionStats const& stats;
+            AssertionResult const& result;
+            std::vector<MessageInfo> messages;
+            std::vector<MessageInfo>::const_iterator itMessage;
+            bool printInfoMessages;
+        };
+
+        // Colour, message variants:
+        // - white: No tests ran.
+        // -   red: Failed [both/all] N test cases, failed [both/all] M assertions.
+        // - white: Passed [both/all] N test cases (no assertions).
+        // -   red: Failed N tests cases, failed M assertions.
+        // - green: Passed [both/all] N tests cases with M assertions.
+
+        std::string bothOrAll( std::size_t count ) const {
+            return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
+        }
+
+        void printTotals( const Totals& totals ) const {
+            if( totals.testCases.total() == 0 ) {
+                stream << "No tests ran.";
+            }
+            else if( totals.testCases.failed == totals.testCases.total() ) {
+                Colour colour( Colour::ResultError );
+                const std::string qualify_assertions_failed =
+                    totals.assertions.failed == totals.assertions.total() ?
+                        bothOrAll( totals.assertions.failed ) : std::string();
+                stream <<
+                    "Failed " << bothOrAll( totals.testCases.failed )
+                              << pluralise( totals.testCases.failed, "test case"  ) << ", "
+                    "failed " << qualify_assertions_failed <<
+                                 pluralise( totals.assertions.failed, "assertion" ) << '.';
+            }
+            else if( totals.assertions.total() == 0 ) {
+                stream <<
+                    "Passed " << bothOrAll( totals.testCases.total() )
+                              << pluralise( totals.testCases.total(), "test case" )
+                              << " (no assertions).";
+            }
+            else if( totals.assertions.failed ) {
+                Colour colour( Colour::ResultError );
+                stream <<
+                    "Failed " << pluralise( totals.testCases.failed, "test case"  ) << ", "
+                    "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
+            }
+            else {
+                Colour colour( Colour::ResultSuccess );
+                stream <<
+                    "Passed " << bothOrAll( totals.testCases.passed )
+                              << pluralise( totals.testCases.passed, "test case"  ) <<
+                    " with "  << pluralise( totals.assertions.passed, "assertion" ) << '.';
+            }
+        }
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
+
+} // end namespace Catch
+
+namespace Catch {
+    // These are all here to avoid warnings about not having any out of line
+    // virtual methods
+    NonCopyable::~NonCopyable() {}
+    IShared::~IShared() {}
+    IStream::~IStream() CATCH_NOEXCEPT {}
+    FileStream::~FileStream() CATCH_NOEXCEPT {}
+    CoutStream::~CoutStream() CATCH_NOEXCEPT {}
+    DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
+    StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
+    IContext::~IContext() {}
+    IResultCapture::~IResultCapture() {}
+    ITestCase::~ITestCase() {}
+    ITestCaseRegistry::~ITestCaseRegistry() {}
+    IRegistryHub::~IRegistryHub() {}
+    IMutableRegistryHub::~IMutableRegistryHub() {}
+    IExceptionTranslator::~IExceptionTranslator() {}
+    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
+    IReporter::~IReporter() {}
+    IReporterFactory::~IReporterFactory() {}
+    IReporterRegistry::~IReporterRegistry() {}
+    IStreamingReporter::~IStreamingReporter() {}
+    AssertionStats::~AssertionStats() {}
+    SectionStats::~SectionStats() {}
+    TestCaseStats::~TestCaseStats() {}
+    TestGroupStats::~TestGroupStats() {}
+    TestRunStats::~TestRunStats() {}
+    CumulativeReporterBase::SectionNode::~SectionNode() {}
+    CumulativeReporterBase::~CumulativeReporterBase() {}
+
+    StreamingReporterBase::~StreamingReporterBase() {}
+    ConsoleReporter::~ConsoleReporter() {}
+    CompactReporter::~CompactReporter() {}
+    IRunner::~IRunner() {}
+    IMutableContext::~IMutableContext() {}
+    IConfig::~IConfig() {}
+    XmlReporter::~XmlReporter() {}
+    JunitReporter::~JunitReporter() {}
+    TestRegistry::~TestRegistry() {}
+    FreeFunctionTestCase::~FreeFunctionTestCase() {}
+    IGeneratorInfo::~IGeneratorInfo() {}
+    IGeneratorsForTest::~IGeneratorsForTest() {}
+    WildcardPattern::~WildcardPattern() {}
+    TestSpec::Pattern::~Pattern() {}
+    TestSpec::NamePattern::~NamePattern() {}
+    TestSpec::TagPattern::~TagPattern() {}
+    TestSpec::ExcludedPattern::~ExcludedPattern() {}
+    Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
+
+    void Config::dummy() {}
+
+    namespace TestCaseTracking {
+        ITracker::~ITracker() {}
+        TrackerBase::~TrackerBase() {}
+        SectionTracker::~SectionTracker() {}
+        IndexTracker::~IndexTracker() {}
+    }
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+// #included from: internal/catch_default_main.hpp
+#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+
+#ifndef __OBJC__
+
+#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
+// Standard C/C++ Win32 Unicode wmain entry point
+extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
+#else
+// Standard C/C++ main entry point
+int main (int argc, char * argv[]) {
+#endif
+
+	int result = Catch::Session().run( argc, argv );
+    return ( result < 0xff ? result : 0xff );
+}
+
+#else // __OBJC__
+
+// Objective-C entry point
+int main (int argc, char * const argv[]) {
+#if !CATCH_ARC_ENABLED
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+    Catch::registerTestMethods();
+    int result = Catch::Session().run( argc, (char* const*)argv );
+
+#if !CATCH_ARC_ENABLED
+    [pool drain];
+#endif
+
+    return ( result < 0xff ? result : 0xff );
+}
+
+#endif // __OBJC__
+
+#endif
+
+#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
+#  undef CLARA_CONFIG_MAIN
+#endif
+
+//////
+
+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
+#ifdef CATCH_CONFIG_PREFIX_ALL
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
+#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
+#else
+#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
+#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr  )
+#endif
+
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
+#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
+
+#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
+#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
+
+#define CATCH_CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
+#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
+
+#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#else
+#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#endif
+
+#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
+#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
+#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
+#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
+#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+    #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+    #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+    #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
+    #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+    #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
+    #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+    #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#else
+    #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+    #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+    #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+    #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
+    #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+    #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
+    #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
+    #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
+#endif
+#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
+#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+#else
+#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
+#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
+#endif
+#define CATCH_GIVEN( desc )    CATCH_SECTION( std::string( "Given: ") + desc, "" )
+#define CATCH_WHEN( desc )     CATCH_SECTION( std::string( " When: ") + desc, "" )
+#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc, "" )
+#define CATCH_THEN( desc )     CATCH_SECTION( std::string( " Then: ") + desc, "" )
+#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc, "" )
+
+// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
+#else
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr )
+#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
+
+#else
+#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr  )
+#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
+#endif
+
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
+#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
+#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
+#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
+
+#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
+#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
+
+#define CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
+#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
+#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
+
+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#else
+#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#endif
+
+#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
+#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
+#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
+#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
+#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#else
+#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+    #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+    #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+    #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
+    #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+    #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
+    #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
+    #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
+#endif
+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+#endif
+
+#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+#else
+#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
+#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
+#endif
+#define GIVEN( desc )    SECTION( std::string("   Given: ") + desc, "" )
+#define WHEN( desc )     SECTION( std::string("    When: ") + desc, "" )
+#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
+#define THEN( desc )     SECTION( std::string("    Then: ") + desc, "" )
+#define AND_THEN( desc ) SECTION( std::string("     And: ") + desc, "" )
+
+using Catch::Detail::Approx;
+
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc
new file mode 100644
index 0000000..0b8c837
--- /dev/null
+++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc
@@ -0,0 +1,339 @@
+// 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.
+
+#include "../catch/catch.hpp"
+#include <thrift/parse/t_program.h>
+#include <thrift/generate/t_netcore_generator.h>
+#include "t_netcore_generator_functional_tests_helpers.h"
+
+TEST_CASE( "t_netcore_generator should generate valid enum", "[functional]" )
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+
+    std::pair<string, t_enum*> pair = TestDataGenerator::get_test_enum_data(program);
+    string expected_result = pair.first;
+    t_enum* test_enum = pair.second;
+
+    string file_path = test_enum->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_enum(out, test_enum));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete test_enum;
+    delete gen;
+    delete program;	
+}
+
+TEST_CASE("t_netcore_generator should generate valid void", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_void_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_THROWS(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid string with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_string_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid bool with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_bool_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid sbyte (i8) with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_i8_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid short (i16) with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_i16_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid integer (i32) with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_i32_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid long (i64) with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_i64_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should generate valid double with escaping keyword", "[functional]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+
+    std::pair<string, t_const*> pair = TestDataGenerator::get_test_double_const_data(gen);
+    string expected_result = pair.first;
+    t_const* const_ = pair.second;
+    vector<t_const*> consts_;
+    consts_.push_back(const_);
+
+    string file_path = const_->get_name() + ".cs";
+    ofstream out;
+    out.open(file_path.c_str());
+
+    REQUIRE_NOTHROW(gen->generate_consts(out, consts_));
+
+    out.close();
+
+    std::ifstream ifs(file_path);
+    string actual_result((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+    std::remove(file_path.c_str());
+
+    REQUIRE(expected_result == actual_result);
+
+    delete const_;
+    delete gen;
+    delete program;
+}
diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc
new file mode 100644
index 0000000..92c170b
--- /dev/null
+++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc
@@ -0,0 +1,237 @@
+// 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.
+
+#include <thrift/parse/t_program.h>
+#include "thrift/common.h"
+#include <thrift/generate/t_netcore_generator.h>
+#include "t_netcore_generator_functional_tests_helpers.h"
+
+const string TestDataGenerator::DEFAULT_FILE_HEADER = "/**" "\n"
+            " * Autogenerated by Thrift Compiler ()" "\n"
+            " *" "\n"
+            " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING" "\n"
+            " *  @generated" "\n"
+            " */";
+
+std::pair<string, t_enum*> TestDataGenerator::get_test_enum_data(t_program* program)
+{
+    string expected_result = DEFAULT_FILE_HEADER +
+        "\n"
+        "\n"
+        "/// <summary>\n"
+        "/// TestDoc\n"
+        "/// </summary>\n"
+        "public enum TestName\n"
+        "{\n"
+        "  None = 0,\n"
+        "  First = 1,\n"
+        "  Second = 2,\n"
+        "}\n";
+
+    t_enum* enum_ = new t_enum(program);
+    enum_->set_name("TestName");
+    enum_->set_doc("TestDoc");
+    enum_->append(new t_enum_value("None", 0));
+    enum_->append(new t_enum_value("First", 1));
+    enum_->append(new t_enum_value("Second", 2));
+
+    return std::pair<string, t_enum*>(expected_result, enum_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_void_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER;
+
+    t_type* type_ = new t_base_type("void", t_base_type::TYPE_VOID);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_string("VoidValue");
+
+    t_const* const_ = new t_const(type_, "void", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_string_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + 
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const string @string = \"StringValue\";\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("string", t_base_type::TYPE_STRING);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_string("StringValue");
+
+    t_const* const_ = new t_const(type_, "string", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_bool_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const bool @bool = true;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("bool", t_base_type::TYPE_BOOL);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_integer(1);
+
+    t_const* const_ = new t_const(type_, "bool", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_i8_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const sbyte @sbyte = 127;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("I8", t_base_type::TYPE_I8);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_integer(127);
+
+    t_const* const_ = new t_const(type_, "sbyte", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_i16_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const short @short = 32767;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("i16", t_base_type::TYPE_I16);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_integer(32767);
+
+    t_const* const_ = new t_const(type_, "short", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_i32_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const int @int = 2147483647;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("i32", t_base_type::TYPE_I32);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_integer(2147483647);
+
+    t_const* const_ = new t_const(type_, "int", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_i64_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const long @long = 9223372036854775807;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("i64", t_base_type::TYPE_I64);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_integer(9223372036854775807);
+
+    t_const* const_ = new t_const(type_, "long", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
+
+std::pair<string, t_const*> TestDataGenerator::get_test_double_const_data(t_netcore_generator* gen)
+{
+    string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() +
+        "\n"
+        "public static class netcoreConstants\n"
+        "{\n"
+        "  /// <summary>\n"
+        "  /// TestDoc\n"
+        "  /// </summary>\n"
+        "  public const double @double = 9.22337e+18;\n"
+        "}\n";
+
+    t_type* type_ = new t_base_type("double", t_base_type::TYPE_DOUBLE);
+    type_->set_doc("TestDoc");
+
+    t_const_value* const_value_ = new t_const_value();
+    const_value_->set_double(9223372036854775807.1);
+
+    t_const* const_ = new t_const(type_, "double", const_value_);
+    const_->set_doc("TestDoc");
+
+    return std::pair<string, t_const*>(expected_result, const_);
+}
diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h
new file mode 100644
index 0000000..c6eaac2
--- /dev/null
+++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h
@@ -0,0 +1,34 @@
+// 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.
+
+#include <thrift/parse/t_program.h>
+
+class TestDataGenerator
+{
+public:
+    static const string DEFAULT_FILE_HEADER;
+
+    static std::pair<string, t_enum*> get_test_enum_data(t_program* program);
+    static std::pair<string, t_const*> get_test_void_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_string_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_bool_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_i8_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_i16_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_i32_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_i64_const_data(t_netcore_generator* gen);
+    static std::pair<string, t_const*> get_test_double_const_data(t_netcore_generator* gen);
+};
diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc
new file mode 100644
index 0000000..0bcbeed
--- /dev/null
+++ b/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc
@@ -0,0 +1,209 @@
+// 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.
+
+#include "../catch/catch.hpp"
+#include <thrift/parse/t_program.h>
+#include <thrift/generate/t_netcore_generator.h>
+
+using std::vector;
+
+TEST_CASE("t_netcore_generator::netcore_type_usings() without option wcf should return valid namespaces", "[helpers]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "union", "union" } };
+    string option_string = "";
+
+    string expected_namespaces = "using System;\n"
+                                "using System.Collections;\n"
+                                "using System.Collections.Generic;\n"
+                                "using System.Text;\n"
+                                "using System.IO;\n"
+                                "using System.Threading;\n"
+                                "using System.Threading.Tasks;\n"
+                                "using Thrift;\n"
+                                "using Thrift.Collections;\n" + endl;
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+
+    REQUIRE_FALSE(gen->is_wcf_enabled());
+    REQUIRE(gen->netcore_type_usings() == expected_namespaces);
+
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator::netcore_type_usings() with option wcf should return valid namespaces", "[helpers]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+
+    string expected_namespaces_wcf = "using System;\n"
+                                    "using System.Collections;\n"
+                                    "using System.Collections.Generic;\n"
+                                    "using System.Text;\n"
+                                    "using System.IO;\n"
+                                    "using System.Threading;\n"
+                                    "using System.Threading.Tasks;\n"
+                                    "using Thrift;\n"
+                                    "using Thrift.Collections;\n"
+                                    "using System.ServiceModel;\n"
+                                    "using System.Runtime.Serialization;\n" + endl;
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+
+    REQUIRE(gen->is_wcf_enabled());
+    REQUIRE(gen->netcore_type_usings() == expected_namespaces_wcf);
+
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should contains latest C# keywords to normalize with @", "[helpers]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" } };
+    string option_string = "";
+    vector<string> current_keywords = {
+        { "abstract" },
+        { "as" },
+        { "base" },
+        { "bool" },
+        { "break" },
+        { "byte" },
+        { "case" },
+        { "catch" },
+        { "char" },
+        { "checked" },
+        { "class" },
+        { "const" },
+        { "continue" },
+        { "decimal" },
+        { "default" },
+        { "delegate" },
+        { "do" },
+        { "double" },
+        { "else" },
+        { "enum" },
+        { "event" },
+        { "explicit" },
+        { "extern" },
+        { "false" },
+        { "finally" },
+        { "fixed" },
+        { "float" },
+        { "for" },
+        { "foreach" },
+        { "goto" },
+        { "if" },
+        { "implicit" },
+        { "in" },
+        { "int" },
+        { "interface" },
+        { "internal" },
+        { "is" },
+        { "lock" },
+        { "long" },
+        { "namespace" },
+        { "new" },
+        { "null" },
+        { "object" },
+        { "operator" },
+        { "out" },
+        { "override" },
+        { "params" },
+        { "private" },
+        { "protected" },
+        { "public" },
+        { "readonly" },
+        { "ref" },
+        { "return" },
+        { "sbyte" },
+        { "sealed" },
+        { "short" },
+        { "sizeof" },
+        { "stackalloc" },
+        { "static" },
+        { "string" },
+        { "struct" },
+        { "switch" },
+        { "this" },
+        { "throw" },
+        { "true" },
+        { "try" },
+        { "typeof" },
+        { "uint" },
+        { "ulong" },
+        { "unchecked" },
+        { "unsafe" },
+        { "ushort" },
+        { "using" },
+        { "void" },
+        { "volatile" },
+        { "while" },
+        // Contextual Keywords
+        { "add" },
+        { "alias" },
+        { "ascending" },
+        { "async" },
+        { "await" },
+        { "descending" },
+        { "dynamic" },
+        { "from" },
+        { "get" },
+        { "global" },
+        { "group" },
+        { "into" },
+        { "join" },
+        { "let" },
+        { "orderby" },
+        { "partial" },
+        { "remove" },
+        { "select" },
+        { "set" },
+        { "value" },
+        { "var" },
+        { "when" },
+        { "where" },
+        { "yield" }
+    };
+
+    string missed_keywords = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+    gen->init_generator();
+    map<string, int> generators_keywords = gen->get_keywords_list();
+
+    for (vector<string>::iterator it = current_keywords.begin(); it != current_keywords.end(); ++it)
+    {
+        if (generators_keywords.find(*it) == generators_keywords.end())
+        {
+            missed_keywords = missed_keywords + *it + ",";
+        }
+    }
+
+    REQUIRE(missed_keywords == "");
+
+    delete gen;
+    delete program;
+}
diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc
new file mode 100644
index 0000000..ec17733
--- /dev/null
+++ b/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc
@@ -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.
+
+#include "../catch/catch.hpp"
+#include <thrift/parse/t_program.h>
+#include <thrift/generate/t_netcore_generator.h>
+
+TEST_CASE( "t_netcore_generator should throw error with unknown options", "[initialization]" )
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "keys", "keys" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = nullptr;
+
+    REQUIRE_THROWS(gen = new t_netcore_generator(program, parsed_options, option_string));	
+
+    delete gen;
+    delete program;	
+}
+
+TEST_CASE("t_netcore_generator should create valid instance with valid options", "[initialization]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" }, { "nullable", "nullable"} };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = nullptr;
+
+    REQUIRE_NOTHROW(gen = new t_netcore_generator(program, parsed_options, option_string));
+    REQUIRE(gen != nullptr);
+    REQUIRE(gen->is_wcf_enabled());
+    REQUIRE(gen->is_nullable_enabled());
+    REQUIRE_FALSE(gen->is_hashcode_enabled());
+    REQUIRE_FALSE(gen->is_serialize_enabled());
+    REQUIRE_FALSE(gen->is_union_enabled());
+
+    delete gen;
+    delete program;
+}
+
+TEST_CASE("t_netcore_generator should pass init succesfully", "[initialization]")
+{
+    string path = "CassandraTest.thrift";
+    string name = "netcore";
+    map<string, string> parsed_options = { { "wcf", "wcf" },{ "nullable", "nullable" } };
+    string option_string = "";
+
+    t_program* program = new t_program(path, name);
+    t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string);
+
+    REQUIRE_NOTHROW(gen->init_generator());
+
+    delete gen;
+    delete program;
+}
diff --git a/compiler/cpp/tests/tests_main.cc b/compiler/cpp/tests/tests_main.cc
new file mode 100644
index 0000000..21d09b9
--- /dev/null
+++ b/compiler/cpp/tests/tests_main.cc
@@ -0,0 +1,19 @@
+// 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.
+
+#define CATCH_CONFIG_MAIN
+#include "catch/catch.hpp"
diff --git a/composer.json b/composer.json
index 0f22b76..1d3a6c0 100644
--- a/composer.json
+++ b/composer.json
@@ -1,9 +1,11 @@
 {
     "name": "apache/thrift",
     "description": "Apache Thrift RPC system",
-    "homepage": "http://thrift.apache.org/",
+    "homepage": "http://thrift.apache.org",
     "type": "library",
+    "keywords": ["RPC"],
     "license": "Apache-2.0",
+    "readme": "README.md",
     "authors": [
         {
             "name": "Apache Thrift Developers",
@@ -16,12 +18,19 @@
         "issues": "https://issues.apache.org/jira/browse/THRIFT"
     },
     "require": {
-        "php": ">=5.3.0"
+        "php": "^5.5 || ^7.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "~4.8.36",
+        "squizlabs/php_codesniffer": "3.*"
     },
     "autoload": {
-        "psr-0": {"Thrift": "lib/php/lib/"}
+        "psr-4": {"Thrift\\": "lib/php/lib/"}
     },
-    "minimum-stability": "dev",
+    "autoload-dev": {
+        "psr-4": {"Test\\Thrift\\": "lib/php/test/"}
+    },
+    "minimum-stability": "stable",
     "extra": {
         "branch-alias": {
             "dev-master": "1.0.x-dev"
diff --git a/configure.ac b/configure.ac
index 6a7a1a5..2174629 100755
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
 AC_PREREQ(2.65)
 AC_CONFIG_MACRO_DIR([./aclocal])
 
-AC_INIT([thrift], [0.11.0])
+AC_INIT([thrift], [1.0.0])
 
 AC_CONFIG_AUX_DIR([.])
 
@@ -102,13 +102,12 @@
 AC_PROG_RANLIB
 
 AC_LANG([C++])
-AX_CXX_COMPILE_STDCXX_11([noext], [optional])
-if test "$ac_success" = "no"; then
-  CXXFLAGS="$CXXFLAGS -Wno-variadic-macros -Wno-long-long -Wno-c++11-long-long"
-fi
+AX_CXX_COMPILE_STDCXX_11([noext], [mandatory])
 
 AM_EXTRA_RECURSIVE_TARGETS([style])
 AC_SUBST(CPPSTYLE_CMD, 'find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;')
+# '
+# The above comment is to fix editor syntax highlighting
 
 AC_ARG_ENABLE([libs],
   AS_HELP_STRING([--enable-libs], [build the Apache Thrift libraries [default=yes]]),
@@ -119,6 +118,7 @@
   have_libs="no"
   with_cpp="no"
   with_c_glib="no"
+  with_cl="no"
   with_java="no"
   with_csharp="no"
   with_python="no"
@@ -135,8 +135,10 @@
   with_go="no"
   with_d="no"
   with_nodejs="no"
+  with_nodets="no"
   with_lua="no"
   with_rs="no"
+  with_swift="no"
 fi
 
 AX_THRIFT_LIB(cpp, [C++], yes)
@@ -153,7 +155,7 @@
     have_cpp="yes"
   fi
 
-  AX_LIB_EVENT([1.0])
+  AX_LIB_EVENT([2.0])
   have_libevent=$success
 
   AX_LIB_ZLIB([1.2.3])
@@ -235,6 +237,7 @@
   AX_CHECK_ANT_VERSION($ANT, 1.7)
   AC_SUBST(CLASSPATH)
   AC_SUBST(ANT_FLAGS)
+  AC_SUBST(GRADLE_OPTS)
   if test "x$JAVA" != "x" && test "x$JAVAC" != "x" && test "x$ANT" != "x" ; then
     have_java="yes"
   fi
@@ -277,6 +280,18 @@
 AM_CONDITIONAL(WITH_NODEJS, [test "$have_nodejs" = "yes"])
 AM_CONDITIONAL(HAVE_NPM, [test "x$NPM" != "x"])
 
+AX_THRIFT_LIB(nodets, [Nodets], yes)
+have_nodets=no
+if test "$with_nodets" = "yes"; then
+  AC_PATH_PROGS([NODETS], [nodets node])
+  AC_PATH_PROG([NPM], [npm])
+  if test "x$NODETS" != "x" -a "x$NPM" != "x"; then
+    have_nodets="yes"
+  fi
+fi
+AM_CONDITIONAL(WITH_NODETS, [test "$have_nodets" = "yes"])
+AM_CONDITIONAL(HAVE_NPM, [test "x$NPM" != "x"])
+
 AX_THRIFT_LIB(lua, [Lua], yes)
 have_lua=no
 if test "$with_lua" = "yes"; then
@@ -307,10 +322,13 @@
 # It's distro specific and far from ideal but needed to cross test py2-3 at once.
 # TODO: find "python2" if it's 3.x
 have_py3="no"
-if python --version 2>&1 | grep -q "Python 2"; then
-  AC_PATH_PROGS([PYTHON3], [python3 python3.5 python35 python3.4 python34])
-  if test -n "$PYTHON3"; then
-    have_py3="yes"
+AX_THRIFT_LIB(py3, [Py3], yes)
+if test "$with_py3" = "yes"; then
+  if $PYTHON --version 2>&1 | grep -q "Python 2"; then
+    AC_PATH_PROGS([PYTHON3], [python3 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34])
+    if test -n "$PYTHON3"; then
+      have_py3="yes"
+    fi
   fi
 fi
 AM_CONDITIONAL(WITH_PY3, [test "$have_py3" = "yes"])
@@ -353,9 +371,6 @@
 fi
 AM_CONDITIONAL(WITH_PHP_EXTENSION, [test "$have_php_extension" = "yes"])
 
-AC_PATH_PROG([PHPUNIT], [phpunit])
-AM_CONDITIONAL(HAVE_PHPUNIT, [test "x$PHPUNIT" != "x"])
-
 AX_THRIFT_LIB(dart, [DART], yes)
 if test "$with_dart" = "yes"; then
   AC_PATH_PROG([DART], [dart])
@@ -431,6 +446,16 @@
 AM_CONDITIONAL(WITH_GO, [test "$have_go" = "yes"])
 AM_CONDITIONAL([GOVERSION_LT_17], [test "$go_version_lt_17" = "yes"])
 
+AX_THRIFT_LIB(swift, [Swift], yes)
+have_swift="no"
+if test "$with_swift" = "yes"; then
+  AC_PATH_PROG([SWIFT], [swift])
+  if test "x$SWIFT" != "x" -a "x$SWIFT" != "x"; then
+    have_swift="yes"
+  fi
+fi
+AM_CONDITIONAL([WITH_SWIFT], [test "$have_swift" = "yes"])
+
 AX_THRIFT_LIB(rs, [Rust], yes)
 have_rs="no"
 if test "$with_rs" = "yes";  then
@@ -455,6 +480,16 @@
 fi
 AM_CONDITIONAL(WITH_RS, [test "$have_rs" = "yes"])
 
+AX_THRIFT_LIB(cl, [Common Lisp], yes)
+have_cl="no"
+if test "$with_cl" = "yes";  then
+  AC_PATH_PROG([SBCL], [sbcl])
+  if test "x$SBCL" != "x"; then
+    have_cl="yes"
+  fi
+fi
+AM_CONDITIONAL(WITH_CL, [test "$have_cl" = "yes"])
+
 AX_THRIFT_LIB(haxe, [Haxe], yes)
 if test "$with_haxe" = "yes";  then
   AC_PATH_PROG([HAXE], [haxe])
@@ -515,7 +550,7 @@
       else
         AX_LIB_EVENT([2.0])
         if test "$success" = "yes"; then
-          DMD_LIBEVENT_FLAGS=$(echo "$LIBEVENT_LDFLAGS $LIBEVENT_LIBS" | \
+          DMD_LIBEVENT_FLAGS=$(echo "-fuse-ld=gold $LIBEVENT_LDFLAGS $LIBEVENT_LIBS" | \
             sed -e 's/^ *//g;s/ *$//g;s/^\(.\)/-L\1/g;s/  */ -L/g')
           with_d_event_tests="yes"
         else
@@ -539,7 +574,7 @@
       else
         AX_CHECK_OPENSSL([with_d_ssl_tests="yes"])
         if test "$with_d_ssl_tests" = "yes"; then
-          DMD_OPENSSL_FLAGS=$(echo "$OPENSSL_LDFLAGS $OPENSSL_LIBS" | \
+          DMD_OPENSSL_FLAGS=$(echo "-fuse-ld=gold $OPENSSL_LDFLAGS $OPENSSL_LIBS" | \
             sed -e 's/^ *//g;s/ *$//g;s/^\(.\)/-L\1/g;s/  */ -L/g')
         else
           AC_MSG_WARN([D OpenSSL interface present, but OpenSSL library not found.])
@@ -624,11 +659,14 @@
 AC_CHECK_HEADERS([netdb.h])
 AC_CHECK_HEADERS([netinet/in.h])
 AC_CHECK_HEADERS([pthread.h])
+AC_CHECK_HEADERS([signal.h])
 AC_CHECK_HEADERS([stddef.h])
 AC_CHECK_HEADERS([stdlib.h])
+AC_CHECK_HEADERS([sys/ioctl.h])
 AC_CHECK_HEADERS([sys/socket.h])
 AC_CHECK_HEADERS([sys/time.h])
 AC_CHECK_HEADERS([sys/un.h])
+AC_CHECK_HEADERS([poll.h])
 AC_CHECK_HEADERS([sys/poll.h])
 AC_CHECK_HEADERS([sys/resource.h])
 AC_CHECK_HEADERS([unistd.h])
@@ -747,24 +785,6 @@
 AC_SUBST(GCOV_CXXFLAGS)
 AC_SUBST(GCOV_LDFLAGS)
 
-AC_ARG_ENABLE(boostthreads,
-              [  --enable-boostthreads      use boost threads, instead of POSIX pthread (experimental) ],
-              [case "${enableval}" in
-                yes) ENABLE_BOOSTTHREADS=1 ;;
-                no) ENABLE_BOOSTTHREADS=0 ;;
-                *) AC_MSG_ERROR(bad value ${enableval} for --enable-cov) ;;
-              esac],
-              [ENABLE_BOOSTTHREADS=2])
-
-
-if test "x[$]ENABLE_BOOSTTHREADS" = "x1"; then
-  AC_MSG_WARN(enable boostthreads)
-  AC_DEFINE([USE_BOOST_THREAD], [1], [experimental --enable-boostthreads that replaces POSIX pthread by boost::thread])
-  LIBS="-lboost_thread $LIBS"
-fi
-
-AM_CONDITIONAL([WITH_BOOSTTHREADS], [test "x[$]ENABLE_BOOSTTHREADS" = "x1"])
-
 AC_CONFIG_HEADERS(config.h:config.hin)
 AC_CONFIG_HEADERS(lib/cpp/src/thrift/config.h:config.hin)
 AC_CONFIG_HEADERS(lib/c_glib/src/thrift/config.h:config.hin)
@@ -786,6 +806,7 @@
   compiler/cpp/test/Makefile
   compiler/cpp/src/thrift/version.h
   lib/Makefile
+  lib/cl/Makefile
   lib/cpp/Makefile
   lib/cpp/test/Makefile
   lib/cpp/thrift-nb.pc
@@ -812,6 +833,7 @@
   lib/json/test/Makefile
   lib/netcore/Makefile
   lib/nodejs/Makefile
+  lib/nodets/Makefile
   lib/perl/Makefile
   lib/perl/test/Makefile
   lib/php/Makefile
@@ -822,11 +844,13 @@
   lib/rs/Makefile
   lib/rs/test/Makefile
   lib/lua/Makefile
+  lib/swift/Makefile
   lib/xml/Makefile
   lib/xml/test/Makefile
   test/Makefile
   test/features/Makefile
   test/c_glib/Makefile
+  test/cl/Makefile
   test/cpp/Makefile
   test/csharp/Makefile
   test/erl/Makefile
@@ -845,6 +869,7 @@
   test/rs/Makefile
   tutorial/Makefile
   tutorial/c_glib/Makefile
+  tutorial/cl/Makefile
   tutorial/cpp/Makefile
   tutorial/d/Makefile
   tutorial/go/Makefile
@@ -890,14 +915,20 @@
 AC_SUBST([MAYBE_GO])
 if test "$have_nodejs" = "yes" ; then MAYBE_NODEJS="nodejs" ; else MAYBE_NODEJS="" ; fi
 AC_SUBST([MAYBE_NODEJS])
+if test "$have_nodets" = "yes" ; then MAYBE_NODETS="nodets" ; else MAYBE_NODETS="" ; fi
+AC_SUBST([MAYBE_NODETS])
 if test "$have_erlang" = "yes" ; then MAYBE_ERLANG="erl" ; else MAYBE_ERLANG="" ; fi
 AC_SUBST([MAYBE_ERLANG])
 if test "$have_lua" = "yes" ; then MAYBE_LUA="lua" ; else MAYBE_LUA="" ; fi
 AC_SUBST([MAYBE_LUA])
 if test "$have_rs" = "yes" ; then MAYBE_RS="rs" ; else MAYBE_RS="" ; fi
 AC_SUBST([MAYBE_RS])
+if test "$have_swift" = "yes" ; then MAYBE_SWIFT="swift" ; else MAYBE_SWIFT="" ; fi
+AC_SUBST([MAYBE_SWIFT])
 if test "$have_dotnetcore" = "yes" ; then MAYBE_DOTNETCORE="netcore" ; else MAYBE_DOTNETCORE="" ; fi
 AC_SUBST([MAYBE_DOTNETCORE])
+if test "$have_cl" = "yes" ; then MAYBE_CL="cl" ; else MAYBE_CL="" ; fi
+AC_SUBST([MAYBE_CL])
 
 AC_OUTPUT
 
@@ -908,6 +939,7 @@
 echo "Building C (GLib) Library .... : $have_c_glib"
 echo "Building C# (Mono) Library ... : $have_csharp"
 echo "Building C++ Library ......... : $have_cpp"
+echo "Building Common Lisp Library.. : $have_cl"
 echo "Building D Library ........... : $have_d"
 echo "Building Dart Library ........ : $have_dart"
 echo "Building dotnetcore Library .. : $have_dotnetcore"
@@ -925,6 +957,7 @@
 echo "Building Py3 Library ......... : $have_py3"
 echo "Building Ruby Library ........ : $have_ruby"
 echo "Building Rust Library ........ : $have_rs"
+echo "Building Swift Library ....... : $have_swift"
 
 if test "$have_csharp" = "yes" ; then
   echo
@@ -942,6 +975,12 @@
   echo "   Build TQTcpServer (Qt5) ... : $have_qt5"
   echo "   C++ compiler version ...... : $($CXX --version | head -1)"
 fi
+if test "$have_cl" = "yes" ; then
+  echo
+  echo "Common Lisp Library:"
+  echo "   Using Common Lisp ......... : $SBCL"
+  echo "   Using Common Lisp version . : $($SBCL --version)"
+fi
 if test "$have_d" = "yes" ; then
   echo
   echo "D Library:"
@@ -992,10 +1031,10 @@
 if test "$have_java" = "yes" ; then
   echo
   echo "Java Library:"
-  echo "   Using ant ................. : $ANT"
+  echo "   Using gradlew ............. : lib/java/gradlew"
   echo "   Using java ................ : $JAVA"
   echo "   Using javac ............... : $JAVAC"
-  echo "   Using ant version ......... : $($ANT -version 2>&1)"
+  echo "   Using Gradle version ...... : $(lib/java/gradlew --version --quiet | grep Gradle 2>&1)"
   echo "   Using java version ........ : $($JAVA -version 2>&1 | grep 'version ')"
 fi
 if test "$have_lua" = "yes" ; then
@@ -1048,6 +1087,12 @@
   echo "   Using rustc................ : $RUSTC"
   echo "   Using Rust version......... : $($RUSTC --version)"
 fi
+if test "$have_swift" = "yes" ; then
+  echo
+  echo "Swift Library:"
+  echo "   Using Swift ............... : $SWIFT"
+  echo "   Using Swift version ....... : $($SWIFT --version | head -1)"
+fi
 echo
 echo "If something is missing that you think should be present,"
 echo "please skim the output of configure to find the missing"
diff --git a/contrib/Rebus/Properties/AssemblyInfo.cs b/contrib/Rebus/Properties/AssemblyInfo.cs
index 9c4d7cc..e476eab 100644
--- a/contrib/Rebus/Properties/AssemblyInfo.cs
+++ b/contrib/Rebus/Properties/AssemblyInfo.cs
@@ -34,5 +34,5 @@
 
 [assembly: Guid("0af10984-40d3-453d-b1e5-421529e8c7e2")]
 
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/contrib/Vagrantfile b/contrib/Vagrantfile
index 3bcc46a..ff53316 100644
--- a/contrib/Vagrantfile
+++ b/contrib/Vagrantfile
@@ -43,7 +43,7 @@
 sudo apt-get install -qq libboost-dev libboost-test-dev libboost-program-options-dev libboost-filesystem-dev libboost-system-dev libevent-dev 
 
 # Java dependencies
-sudo apt-get install -qq ant openjdk-7-jdk maven
+sudo apt-get install -qq ant openjdk-8-jdk maven
 
 # Python dependencies
 sudo apt-get install -qq python-all python-all-dev python-all-dbg python-setuptools python-support python-six python3-six
@@ -89,8 +89,8 @@
 
 # Customize the system
 # ---
-# Default java to latest 1.7 version
-update-java-alternatives -s java-1.7.0-openjdk-amd64 
+# Default java to latest 1.8 version
+update-java-alternatives -s java-1.8.0-openjdk-amd64 
 
 # PHPUnit package broken in ubuntu. see https://bugs.launchpad.net/ubuntu/+source/phpunit/+bug/701544
 sudo apt-get upgrade pear
diff --git a/contrib/fb303/cpp/FacebookBase.h b/contrib/fb303/cpp/FacebookBase.h
index 2159c95..daa5246 100644
--- a/contrib/fb303/cpp/FacebookBase.h
+++ b/contrib/fb303/cpp/FacebookBase.h
@@ -22,6 +22,7 @@
 
 #include "FacebookService.h"
 
+#include <boost/shared_ptr.hpp>
 #include <thrift/server/TServer.h>
 #include <thrift/concurrency/Mutex.h>
 
diff --git a/contrib/fb303/java/build.properties b/contrib/fb303/java/build.properties
new file mode 100644
index 0000000..8463668
--- /dev/null
+++ b/contrib/fb303/java/build.properties
@@ -0,0 +1,5 @@
+# Maven Ant tasks Jar details
+mvn.ant.task.version=2.1.3
+mvn.repo=http://repo1.maven.org/maven2
+mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version}
+mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar
diff --git a/contrib/fb303/java/build.xml b/contrib/fb303/java/build.xml
index 8f2fa51..7a1b8f1 100755
--- a/contrib/fb303/java/build.xml
+++ b/contrib/fb303/java/build.xml
@@ -7,9 +7,9 @@
  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
@@ -26,20 +26,20 @@
   <property name="interface.dir" value="${basedir}/../if"/>
   <property name="thrift.java.dir" location="${thrift.root}/lib/java"/>
   <property name="build.tools.dir" location="${thrift.java.dir}/build/tools/"/>
-  <property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/> 
+  <property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/>
+  <property file="${basedir}/build.properties"/>
 
   <!-- inherit from the java build file for version and other properties -->
-  <property file="${thrift.java.dir}/build.properties" />
+  <property file="${thrift.java.dir}/gradle.properties" />
 
   <property environment="env"/>
 
   <condition property="version" value="${thrift.version}">
     <isset property="release"/>
   </condition>
-  <property name="version" value="${thrift.version}-snapshot"/>
+  <property name="version" value="${thrift.version}-SNAPSHOT"/>
 
   <property name="fb303.final.name" value="${fb303.artifactid}-${version}"/>
-  <property name="thrift.java.libthrift" value="${thrift.java.dir}/build/libthrift-${version}.jar"/>
 
   <property name="src" value="${basedir}/src"/>
   <property name="gen" value="${basedir}/gen-java"/>
@@ -74,8 +74,12 @@
     <echo message="Building ${fb303.final.name}.jar"/>
     <javac destdir="${build.classes.dir}" debug="on">
       <classpath>
-        <pathelement location="${thrift.java.libthrift}"/>
-        <fileset dir="${thrift.root}/lib/java/build/lib">
+        <fileset dir="${thrift.java.dir}/build/libs">
+          <include name="libthrift*.jar" />
+          <exclude name="libthrift*javadoc.jar" />
+          <exclude name="libthrift*sources.jar" />
+        </fileset>
+        <fileset dir="${thrift.java.dir}/build/deps">
           <include name="*.jar"/>
         </fileset>
       </classpath>
@@ -120,21 +124,21 @@
     <artifact:remoteRepository id="apache" url="${apache.repo}"/>
 
     <!-- Pom file information -->
-    <artifact:pom id="pom" 
-      groupId="${thrift.groupid}" 
+    <artifact:pom id="pom"
+      groupId="${thrift.groupid}"
       artifactId="${fb303.artifactid}"
-      version="${version}" 
+      version="${version}"
       url="http://thrift.apache.org"
       name="Apache Thrift"
       description="Thrift is a software framework for scalable cross-language services development."
-      packaging="pom"
+      packaging="jar"
     >
       <remoteRepository refid="central"/>
       <remoteRepository refid="apache"/>
       <license name="The Apache Software License, Version 2.0" url="${license}"/>
-      <scm connection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git" 
-      developerConnection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
-      url="https://git-wip-us.apache.org/repos/asf?p=thrift.git"
+      <scm connection="scm:git:https://github.com/apache/thrift.git"
+      developerConnection="scm:git:https://github.com/apache/thrift.git"
+      url="https://github.com/apache/thrift"
     />
       <!-- Thrift Developers -->
       <developer id="mcslee" name="Mark Slee"/>
diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py
index 9dafa88..d27c296 100644
--- a/contrib/fb303/py/setup.py
+++ b/contrib/fb303/py/setup.py
@@ -26,9 +26,9 @@
     from distutils.core import setup, Extension, Command
 
 setup(name='thrift_fb303',
-      version='0.11.0',
+      version='1.0.0',
       description='Python bindings for the Apache Thrift FB303',
-      author=['Thrift Developers'],
+      author=['Apache Thrift Developers'],
       author_email=['dev@thrift.apache.org'],
       url='http://thrift.apache.org',
       license='Apache License 2.0',
@@ -37,7 +37,7 @@
           'fb303_scripts',
       ],
       classifiers=[
-          'Development Status :: 5 - Production/Stable',
+          'Development Status :: 7 - Inactive',
           'Environment :: Console',
           'Intended Audience :: Developers',
           'Programming Language :: Python',
diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml
index 76d0d4f..b65f6aa 100644
--- a/contrib/thrift-maven-plugin/pom.xml
+++ b/contrib/thrift-maven-plugin/pom.xml
@@ -7,9 +7,9 @@
  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
@@ -17,8 +17,8 @@
  specific language governing permissions and limitations
  under the License.
  -->
-<project 
-  xmlns="http://maven.apache.org/POM/4.0.0" 
+<project
+  xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
@@ -27,15 +27,15 @@
   <artifactId>thrift-maven-plugin</artifactId>
   <packaging>maven-plugin</packaging>
   <name>thrift-maven-plugin</name>
-  <version>0.11.0</version>
+  <version>1.0.0</version>
   <build>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <source>1.7</source>
-          <target>1.7</target>
+          <source>1.8</source>
+          <target>1.8</target>
         </configuration>
       </plugin>
       <plugin>
diff --git a/contrib/thrift.spec b/contrib/thrift.spec
index 034ebc8..cc3c33c 100644
--- a/contrib/thrift.spec
+++ b/contrib/thrift.spec
@@ -28,7 +28,7 @@
 License:        Apache License v2.0
 Group:          Development
 Summary:        RPC and serialization framework
-Version:        0.11.0
+Version:        1.0.0
 Release:        0
 URL:            http://thrift.apache.org
 Packager:       Thrift Developers <dev@thrift.apache.org>
@@ -178,6 +178,19 @@
   --without-csharp \
   --without-erlang \
 
+%if 0%{!?without_ruby:1}
+eval $(grep "^WITH_RUBY_TRUE" config.log)
+if [[ "${WITH_RUBY_TRUE}" != "" ]]; then
+  set +x
+  echo ""
+  echo "configure determined that ruby requirements are missing (bundler gem?), either install missing components" >&2
+  echo "or disable the ruby sub-packages as follows:"                                                              >&2
+  echo "     rpmbuild -D'%without_ruby 1' ..."                                                                     >&2
+  echo ""
+  exit 1
+fi
+%endif
+
 make %{?_smp_mflags}
 
 %if 0%{!?without_java:1}
@@ -234,5 +247,7 @@
 /sbin/ldconfig > /dev/null 2>&1
 
 %changelog
+* Wed Aug 21 2013 Thrift Dev <dev@thrift.apache.org>
+- Thrift 0.9.1 release.
 * Wed Oct 10 2012 Thrift Dev <dev@thrift.apache.org> 
 - Thrift 0.9.0 release.
diff --git a/contrib/transport-sample/ThriftCommon.h b/contrib/transport-sample/ThriftCommon.h
index d24d1a7..e16d87d 100644
--- a/contrib/transport-sample/ThriftCommon.h
+++ b/contrib/transport-sample/ThriftCommon.h
@@ -16,8 +16,6 @@
 //
 
 #ifdef _WIN32 //thrift is crashing when using boost threads on Mac OSX
-#  define USE_BOOST_THREAD 1
-#  include <boost/thread.hpp>
 #else
 #  include <sys/socket.h>
 #  include <netinet/in.h>
diff --git a/contrib/vagrant/centos-6.5/README.md b/contrib/vagrant/centos-6.5/README.md
index bd7f022..55583f9 100644
--- a/contrib/vagrant/centos-6.5/README.md
+++ b/contrib/vagrant/centos-6.5/README.md
@@ -11,7 +11,7 @@
    $ vagrant ssh
    [vagrant@thrift ~]$ cd /thrift
    [vagrant@thrift thrift]$ compiler/cpp/thrift --version
-   Thrift version 0.11.0
+   Thrift version <version>
 
 The provisioning script (inside the Vagrantfile) runs ./bootstrap.sh, ./configure, make and make check, but does not install thrift. To install thrift run "make install".
 
diff --git a/contrib/vagrant/centos-6.5/Vagrantfile b/contrib/vagrant/centos-6.5/Vagrantfile
index 6207958..51a2239 100644
--- a/contrib/vagrant/centos-6.5/Vagrantfile
+++ b/contrib/vagrant/centos-6.5/Vagrantfile
@@ -87,7 +87,7 @@
 
 # Java LIB Dependencies
 #####################################
-sudo yum install -y ant junit ant-nodeps ant-junit java-1.7.0-openjdk-devel
+sudo yum install -y ant junit ant-nodeps ant-junit java-1.8.0-openjdk-devel
 
 # Python LIB Dependencies
 #####################################
diff --git a/contrib/zeromq/Makefile b/contrib/zeromq/Makefile
index b09f4ee..ee398e2 100644
--- a/contrib/zeromq/Makefile
+++ b/contrib/zeromq/Makefile
@@ -26,7 +26,7 @@
 
 storage/__init__.py: storage.thrift
 	$(RM) $(dir $@)
-	$(THRIFT) --gen py:newstyle $<
+	$(THRIFT) --gen py $<
 	mv gen-py/$(dir $@) .
 
 $(GENSRCS): storage.thrift
diff --git a/contrib/zeromq/TZmqServer.cpp b/contrib/zeromq/TZmqServer.cpp
index f031458..88660a3 100644
--- a/contrib/zeromq/TZmqServer.cpp
+++ b/contrib/zeromq/TZmqServer.cpp
@@ -21,7 +21,7 @@
 #include <thrift/transport/TBufferTransports.h>
 #include <boost/scoped_ptr.hpp>
 
-using boost::shared_ptr;
+using apache::thrift::std::shared_ptr;
 using apache::thrift::transport::TMemoryBuffer;
 using apache::thrift::protocol::TProtocol;
 
diff --git a/contrib/zeromq/TZmqServer.h b/contrib/zeromq/TZmqServer.h
index a840c86..ecd13b4 100644
--- a/contrib/zeromq/TZmqServer.h
+++ b/contrib/zeromq/TZmqServer.h
@@ -20,6 +20,7 @@
 #ifndef _THRIFT_SERVER_TZMQSERVER_H_
 #define _THRIFT_SERVER_TZMQSERVER_H_ 1
 
+#include <memory>
 #include <zmq.hpp>
 #include <thrift/server/TServer.h>
 
@@ -28,7 +29,7 @@
 class TZmqServer : public TServer {
  public:
   TZmqServer(
-      boost::shared_ptr<TProcessor> processor,
+      std::shared_ptr<TProcessor> processor,
       zmq::context_t& ctx, const std::string& endpoint, int type)
     : TServer(processor)
     , processor_(processor)
@@ -56,7 +57,7 @@
   }
 
  private:
-  boost::shared_ptr<TProcessor> processor_;
+  std::shared_ptr<TProcessor> processor_;
   int zmq_type_;
   zmq::socket_t sock_;
 };
diff --git a/contrib/zeromq/csharp/ThriftZMQ.csproj b/contrib/zeromq/csharp/ThriftZMQ.csproj
index 32a8c49..80ad1db 100755
--- a/contrib/zeromq/csharp/ThriftZMQ.csproj
+++ b/contrib/zeromq/csharp/ThriftZMQ.csproj
@@ -1,22 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-  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.
--->
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -43,7 +25,7 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
@@ -106,4 +88,4 @@
     </BootstrapperPackage>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-</Project>
\ No newline at end of file
+</Project>
diff --git a/contrib/zeromq/test-client.cpp b/contrib/zeromq/test-client.cpp
index d2fc56c..159c250 100644
--- a/contrib/zeromq/test-client.cpp
+++ b/contrib/zeromq/test-client.cpp
@@ -6,7 +6,7 @@
 #include "TZmqClient.h"
 #include "Storage.h"
 
-using boost::shared_ptr;
+using apache::thrift::std::shared_ptr;
 using apache::thrift::transport::TZmqClient;
 using apache::thrift::protocol::TBinaryProtocol;
 
@@ -17,7 +17,7 @@
   if (argc > 1) {
     incr = atoi(argv[1]);
     if (incr) {
-      socktype = ZMQ_DOWNSTREAM;
+      socktype = ZMQ_PUSH;
       endpoint = "tcp://127.0.0.1:9091";
     }
   }
diff --git a/contrib/zeromq/test-client.py b/contrib/zeromq/test-client.py
index 55c23e0..d51216e 100755
--- a/contrib/zeromq/test-client.py
+++ b/contrib/zeromq/test-client.py
@@ -15,7 +15,7 @@
     if len(args) > 1:
         incr = int(args[1])
         if incr:
-            socktype = zmq.DOWNSTREAM
+            socktype = zmq.PUSH
             endpoint = "tcp://127.0.0.1:9091"
 
     ctx = zmq.Context()
diff --git a/contrib/zeromq/test-receiver.cpp b/contrib/zeromq/test-receiver.cpp
index 8fe69da..d465bff 100644
--- a/contrib/zeromq/test-receiver.cpp
+++ b/contrib/zeromq/test-receiver.cpp
@@ -2,7 +2,7 @@
 #include "TZmqServer.h"
 #include "Storage.h"
 
-using boost::shared_ptr;
+using apache::thrift::std::shared_ptr;
 using apache::thrift::TProcessor;
 using apache::thrift::server::TZmqServer;
 using apache::thrift::server::TZmqMultiServer;
diff --git a/contrib/zeromq/test-sender.cpp b/contrib/zeromq/test-sender.cpp
index 6b0eef1..5c086a1 100644
--- a/contrib/zeromq/test-sender.cpp
+++ b/contrib/zeromq/test-sender.cpp
@@ -6,7 +6,7 @@
 #include "TZmqClient.h"
 #include "Storage.h"
 
-using boost::shared_ptr;
+using apache::thrift::std::shared_ptr;
 using apache::thrift::transport::TZmqClient;
 using apache::thrift::protocol::TBinaryProtocol;
 
diff --git a/contrib/zeromq/test-server.cpp b/contrib/zeromq/test-server.cpp
index c624b0d..e6f1b20 100644
--- a/contrib/zeromq/test-server.cpp
+++ b/contrib/zeromq/test-server.cpp
@@ -2,7 +2,7 @@
 #include "TZmqServer.h"
 #include "Storage.h"
 
-using boost::shared_ptr;
+using apache::thrift::std::shared_ptr;
 using apache::thrift::TProcessor;
 using apache::thrift::server::TZmqServer;
 using apache::thrift::server::TZmqMultiServer;
@@ -33,7 +33,7 @@
 
   zmq::context_t ctx(1);
   TZmqServer reqrep_server(processor, ctx, "tcp://0.0.0.0:9090", ZMQ_REP);
-  TZmqServer oneway_server(processor, ctx, "tcp://0.0.0.0:9091", ZMQ_UPSTREAM);
+  TZmqServer oneway_server(processor, ctx, "tcp://0.0.0.0:9091", ZMQ_PULL);
   TZmqMultiServer multiserver;
   multiserver.servers().push_back(&reqrep_server);
   multiserver.servers().push_back(&oneway_server);
diff --git a/contrib/zeromq/test-server.py b/contrib/zeromq/test-server.py
index c7804d3..d89b37b 100755
--- a/contrib/zeromq/test-server.py
+++ b/contrib/zeromq/test-server.py
@@ -22,7 +22,7 @@
 
     ctx = zmq.Context()
     reqrep_server = TZmqServer.TZmqServer(processor, ctx, "tcp://0.0.0.0:9090", zmq.REP)
-    oneway_server = TZmqServer.TZmqServer(processor, ctx, "tcp://0.0.0.0:9091", zmq.UPSTREAM)
+    oneway_server = TZmqServer.TZmqServer(processor, ctx, "tcp://0.0.0.0:9091", zmq.PULL)
     multiserver = TZmqServer.TZmqMultiServer()
     multiserver.servers.append(reqrep_server)
     multiserver.servers.append(oneway_server)
diff --git a/debian/changelog b/debian/changelog
index 68629d6..69b5f20 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,26 @@
+thrift (0.12.0) stable; urgency=low
+
+  * update to 0.12.0
+
+ -- Apache Thrift Developers <dev@thrift.apache.org>  Wed, 28 Dec 2018 12:00:00 -0500
+
 thrift (0.11.0) stable; urgency=low
-  * update version
-  * fix libthrift0.install
 
   * update to 0.11.0
- -- Roger Meier <roger@apache.org>  Tue, 08 Jan 2013 22:40:12 +0100
+
+ -- Jake Farrell <jfarrell@apache.org>  Wed, 07 Dec 2017 20:07:00 -0500
+
+thrift (0.10.0) stable; urgency=low
+
+  * update to 0.10.0
+
+ -- Jake Farrell <jfarrell@apache.org>  Wed, 03 Jan 2017 16:52:00 -0500
+
+thrift (0.9.3) stable; urgency=low
+
+  * update to 0.9.3
+
+ -- Jake Farrell <jfarrell@apache.org>  Wed, 11 Oct 2015 17:22:00 -0500
 
 thrift (0.9.0) stable; urgency=low
 
diff --git a/debian/control b/debian/control
index 218d217..9818a37 100644
--- a/debian/control
+++ b/debian/control
@@ -3,16 +3,16 @@
 Priority: extra
 Build-Depends: debhelper (>= 9), build-essential, mono-mcs, python-dev, ant,
     mono-devel,  libmono-system-web4.0-cil, erlang-base, ruby-dev | ruby1.9.1-dev, ruby-bundler ,autoconf, automake,
-    pkg-config, libtool, bison, flex, libboost-dev | libboost1.53-dev,
+    pkg-config, libtool, bison, flex, libboost-dev | libboost1.53-dev | libboost1.63-all-dev,
     python-all, python-setuptools, python-all-dev, python-all-dbg,
     python3-all, python3-setuptools, python3-all-dev, python3-all-dbg,
     openjdk-7-jdk | openjdk-8-jdk | default-jdk,
-    libboost-test-dev | libboost-test1.53-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7),
-    php5 | php7.0, php5-dev | php7.0-dev, libglib2.0-dev, qtchooser, qtbase5-dev-tools
+    libboost-test-dev | libboost-test1.53-dev | libboost-test1.63-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7),
+    php (>= 5), php-dev (>= 5), libglib2.0-dev, qtchooser, qtbase5-dev-tools
 Maintainer: Thrift Developer's <dev@thrift.apache.org>
 Homepage: http://thrift.apache.org/
-Vcs-Git: https://git-wip-us.apache.org/repos/asf/thrift.git
-Vcs-Browser: https://git-wip-us.apache.org/repos/asf?p=thrift.git
+Vcs-Git: https://github.com/apache/thrift.git
+Vcs-Browser: https://github.com/apache/thrift
 Standards-Version: 3.9.7
 X-Python-Version: >= 2.6
 X-Python3-Version: >= 3.3
diff --git a/debian/rules b/debian/rules
index f370325..9b436d9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -73,7 +73,7 @@
 
 	# Java
 	cd $(CURDIR)/lib/java && \
-		ant
+		./gradlew --no-daemon -Prelease=true jar
 
 	# C#
 	$(MAKE) -C $(CURDIR)/lib/csharp
@@ -113,7 +113,7 @@
 
 	# Java
 	mkdir -p $(CURDIR)/debian/libthrift-java/usr/share/java/ && \
-	cp $(CURDIR)/lib/java/build/libthrift*.jar \
+	cp $(CURDIR)/lib/java/build/libs/libthrift*.jar \
 		$(CURDIR)/debian/libthrift-java/usr/share/java/
 
 	# Ruby
diff --git a/doap.rdf b/doap.rdf
index 06447c7..cb76fac 100755
--- a/doap.rdf
+++ b/doap.rdf
@@ -60,6 +60,11 @@
     <release rdf:parseType="Collection">
       <Version>
         <name>Apache Thrift</name>
+        <created>2018-12-28</created>
+        <revision>0.12.0</revision>
+      </Version>
+      <Version>
+        <name>Apache Thrift</name>
         <created>2017-11-30</created>
         <revision>0.11.0</revision>
       </Version>
@@ -131,8 +136,8 @@
     </release>
     <repository>
       <GitRepository>
-        <location rdf:resource="https://git-wip-us.apache.org/repos/asf/thrift.git"/>
-        <browse rdf:resource="https://git-wip-us.apache.org/repos/asf?p=thrift.git"/>
+        <location rdf:resource="https://github.com/apache/thrift.git"/>
+        <browse rdf:resource="https://github.com/apache/thrift"/>
       </GitRepository>
     </repository>
     <maintainer>
diff --git a/doc/committers.md b/doc/committers.md
index b02edbe..dcdd7b7 100644
--- a/doc/committers.md
+++ b/doc/committers.md
@@ -4,7 +4,7 @@
 
 1. Check out the latest version of the source code
 
-  * git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift
+  * git clone https://github.com/apache/thrift.git thrift
 
 1. Apply the patch
 
diff --git a/doc/install/README.md b/doc/install/README.md
index e37f4ff..22231cd 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -27,7 +27,7 @@
     * libevent (optional, to build the nonblocking server)
     * zlib (optional)
 * Java
-    * Java 1.7
+    * Java 1.8
     * Apache Ant
 * C#: Mono 1.2.4 (and pkg-config to detect it) or Visual Studio 2005+
 * Python 2.6 (including header files for extension modules)
diff --git a/doc/install/centos.md b/doc/install/centos.md
index 609e118..04932c2 100644
--- a/doc/install/centos.md
+++ b/doc/install/centos.md
@@ -64,7 +64,7 @@
 
 ## Build and Install the Apache Thrift IDL Compiler
 
-	git clone https://git-wip-us.apache.org/repos/asf/thrift.git
+	git clone https://github.com/apache/thrift.git
 	cd thrift
 	./bootstrap.sh
 	./configure --with-lua=no
diff --git a/doc/install/debian.md b/doc/install/debian.md
index 5e1ae4c..84f696e 100644
--- a/doc/install/debian.md
+++ b/doc/install/debian.md
@@ -1,7 +1,7 @@
 ## Debian/Ubuntu install
 The following command will install tools and libraries required to build and install the Apache Thrift compiler and C++ libraries on a Debian/Ubuntu Linux based system.
 
-	sudo apt-get install automake bison flex g++ git libboost1.55-all-dev libevent-dev libssl-dev libtool make pkg-config
+	sudo apt-get install automake bison flex g++ git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config
 
 Debian 7/Ubuntu 12 users need to manually install a more recent version of automake and (for C++ library and test support) boost:
 
@@ -18,9 +18,10 @@
 If you would like to build Apache Thrift libraries for other programming languages you may need to install additional packages. The following languages require the specified additional packages:
 
  * Java
-	* To build Apache Thrift support for Java you will need to install the ant package and Java JDK v1.7 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. openjdk-7-jdk).
+	* packages: ant  
+	* You will also need Java JDK v1.8 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. default-jdk).
  * Ruby
-	* ruby-full ruby-dev ruby-rspec rake rubygems libdaemons-ruby libgemplugin-ruby mongrel
+	* ruby-full ruby-dev ruby-rspec rake rubygems bundler
  * Python
 	* python-all python-all-dev python-all-dbg
  * Perl
@@ -30,14 +31,29 @@
  * C_glib
 	* libglib2.0-dev
  * Erlang
-	* erlang-base erlang-eunit erlang-dev
+	* erlang-base erlang-eunit erlang-dev rebar
  * Csharp
 	* mono-gmcs mono-devel libmono-system-web2.0-cil nunit nunit-console
  * Haskell
-	* ghc6 cabal-install libghc6-binary-dev libghc6-network-dev libghc6-http-dev
+	* ghc cabal-install libghc-binary-dev libghc-network-dev libghc-http-dev
  * Thrift Compiler for Windows
-	* mingw32 mingw32-binutils mingw32-runtime nsis
-
+	* mingw-w64 mingw-w64-x86-64-dev nsis
+ * Rust
+	* rustc cargo
+ * Haxe
+	* haxe
+ * Lua
+    * lua5.3 liblua5.3-dev
+ * NodeJs
+    * nodejs npm
+ * dotnetcore
+    * https://www.microsoft.com/net/learn/get-started/linuxubuntu
+ * d-lang
+    * curl -fsS https://dlang.org/install.sh | bash -s dmd
+ * dart & pub
+    * https://www.dartlang.org/install/linux
+    * https://www.dartlang.org/tools/pub/installing
+	
 
 ## Additional reading
 
diff --git a/doc/install/windows.md b/doc/install/windows.md
index 7b09840..8618934 100644
--- a/doc/install/windows.md
+++ b/doc/install/windows.md
@@ -145,7 +145,7 @@
 
 Make sure you have java in your $PATH variable, if not do(adjust path if necessary):
 
-	export PATH=$PATH:"/cygdrive/c/program files/java/jre1.6.0_05/bin"
+	export PATH=$PATH:"/cygdrive/c/program files/java/jre1.8.0_191/bin"
 
 Run configure - using CXXFLAGS to work around an issue with an old pthreads define (untested on MinGW - works on Cygwin):
 
diff --git a/doc/specs/idl.md b/doc/specs/idl.md
index b7eb23c..bf22f54 100644
--- a/doc/specs/idl.md
+++ b/doc/specs/idl.md
@@ -156,7 +156,7 @@
 - Read: Like optional, the field may, or may not be part of the input stream. 
 - Default values: may not be written (see next section)
 
-Default requiredess is a good starting point. The desired behaviour is a mix of optional and required, hence the internal name "opt-in, req-out". Although in theory these fields are supposed to be written ("req-out"), in reality unset fields are not always written. This is especially the case, when the field contains a <null> value, which by definition cannot be transported through thrift. The only way to achieve this is by not writing that field at all, and that's what most languages do.
+Default requiredness is a good starting point. The desired behaviour is a mix of optional and required, hence the internal name "opt-in, req-out". Although in theory these fields are supposed to be written ("req-out"), in reality unset fields are not always written. This is especially the case, when the field contains a <null> value, which by definition cannot be transported through thrift. The only way to achieve this is by not writing that field at all, and that's what most languages do.
 	
 #### Semantics of Default Values
 
@@ -242,9 +242,9 @@
  * [Apache Cassandra's][] Thrift IDL: [cassandra.thrift][]
  * [Evernote API][]
 
- [ThriftTest.thrift]:  https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_plain;f=test/ThriftTest.thrift;hb=HEAD
+ [ThriftTest.thrift]:  https://raw.githubusercontent.com/apache/thrift/master/test/ThriftTest.thrift
  [tutorial]:           /tutorial/
- [fb303.thrift]:       https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_plain;f=contrib/fb303/if/fb303.thrift;hb=HEAD
+ [fb303.thrift]:       https://raw.githubusercontent.com/apache/thrift/master/contrib/fb303/if/fb303.thrift
  [Apache Cassandra's]: http://cassandra.apache.org/
  [cassandra.thrift]:   http://svn.apache.org/viewvc/cassandra/trunk/interface/cassandra.thrift?view=co
  [Evernote API]:       http://www.evernote.com/about/developer/api/
diff --git a/dub.json b/dub.json
new file mode 100644
index 0000000..af76afc
--- /dev/null
+++ b/dub.json
@@ -0,0 +1,28 @@
+{
+  "name": "apache-thrift",
+  "description": "Apache Thrift D library",
+  "authors": [
+    "Apache Thrift Developers <dev@thrift.apache.org>"
+  ],
+  "homepage": "http://thrift.apache.org",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "libevent": {
+      "version": "~>2.0.2"
+    },
+    "openssl": {
+      "version": ">=1.1.6"
+    }
+  },
+  "systemDependencies": "On systems with native openssl 1.0.x use dub package openssl~>1.1, on systems with native openssl 1.1.x use dub package openssl~>2.0",
+  "targetType": "library",
+  "sourcePaths": [
+    "lib/d/src" 
+  ],
+  "importPaths": [
+    "lib/d/src"
+  ],
+  "excludedSourceFiles": [
+    "lib/d/src/thrift/index.d"
+  ]
+}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 636f42c..b6ce20e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -87,6 +87,7 @@
 if WITH_NODEJS
 SUBDIRS += nodejs
 PRECROSS_TARGET += precross-nodejs
+SUBDIRS += nodets
 endif
 
 if WITH_LUA
@@ -97,6 +98,14 @@
 SUBDIRS += rs
 endif
 
+if WITH_CL
+SUBDIRS += cl
+endif
+
+if WITH_SWIFT
+SUBDIRS += swift
+endif
+
 # All of the libs that don't use Automake need to go in here
 # so they will end up in our release tarballs.
 EXTRA_DIST = \
diff --git a/lib/as3/build.properties b/lib/as3/build.properties
new file mode 100644
index 0000000..8463668
--- /dev/null
+++ b/lib/as3/build.properties
@@ -0,0 +1,5 @@
+# Maven Ant tasks Jar details
+mvn.ant.task.version=2.1.3
+mvn.repo=http://repo1.maven.org/maven2
+mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version}
+mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar
diff --git a/lib/as3/build.xml b/lib/as3/build.xml
index 604da42..b0c4c85 100755
--- a/lib/as3/build.xml
+++ b/lib/as3/build.xml
@@ -7,9 +7,9 @@
  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
@@ -19,23 +19,24 @@
  -->
 <project name="libthrift-as3" default="compile" basedir="."
   xmlns:artifact="antlib:org.apache.maven.artifact.ant">
-	
+
   <property name="as3.artifactid" value="${ant.project.name}"/>
-	
+
   <property name="thrift.root" location="${basedir}/../../"/>
   <property name="thrift.java.dir" location="${thrift.root}/lib/java"/>
   <property name="build.tools.dir" location="${thrift.java.dir}/build/tools/"/>
-  <property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/> 
+  <property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/>
+  <property file="${basedir}/build.properties"/>
 
   <!-- inherit from the java build file for version and other properties -->
-  <property file="${thrift.java.dir}/build.properties" />
+  <property file="${thrift.java.dir}/gradle.properties" />
 
   <property environment="env"/>
 
   <condition property="version" value="${thrift.version}">
     <isset property="release"/>
   </condition>
-  <property name="version" value="${thrift.version}-snapshot"/>
+  <property name="version" value="${thrift.version}-SNAPSHOT"/>
 
   <property name="as3.final.name" value="${as3.artifactid}-${version}"/>
 
@@ -52,12 +53,13 @@
   <target name="setup.init">
     <tstamp/>
     <mkdir dir="${build.dir}"/>
+    <mkdir dir="${build.tools.dir}"/>
   </target>
 
   <target name="flex.check" unless="FLEX_HOME">
     <fail message='You must set the FLEX_HOME property pointing to your flex SDK, eg. ant -DFLEX_HOME="/Applications/Adobe Flex Builder 3/sdks/3.2.0"'/>
   </target>
-	
+
   <target name="flex.init" depends="flex.check" unless="flex.finished">
     <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
     <property name="flex.finished" value="true"/>
@@ -69,10 +71,10 @@
         <include name="**/*.as"/>
       </fileset>
     </path>
-    <pathconvert 
-      property="as.src.classes" 
-      pathsep=" " 
-      dirsep="." 
+    <pathconvert
+      property="as.src.classes"
+      pathsep=" "
+      dirsep="."
       refid="as.src.files"
     >
       <map from="${src}/" to=""/>
@@ -108,21 +110,21 @@
     <artifact:remoteRepository id="apache" url="${apache.repo}"/>
 
     <!-- Pom file information -->
-    <artifact:pom id="pom" 
-      groupId="${thrift.groupid}" 
+    <artifact:pom id="pom"
+      groupId="${thrift.groupid}"
       artifactId="${as3.artifactid}"
-      version="${version}" 
+      version="${version}"
       url="http://thrift.apache.org"
       name="Apache Thrift"
       description="Thrift is a software framework for scalable cross-language services development."
-      packaging="pom"
+      packaging="swc"
     >
       <remoteRepository refid="central"/>
       <remoteRepository refid="apache"/>
       <license name="The Apache Software License, Version 2.0" url="${license}"/>
-      <scm connection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git" 
-      developerConnection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
-      url="https://git-wip-us.apache.org/repos/asf?p=thrift.git"
+      <scm connection="scm:git:https://github.com/apache/thrift.git"
+      developerConnection="scm:git:https://github.com/apache/thrift.git"
+      url="https://github.com/apache/thrift"
       />
       <!-- Thrift Developers -->
       <developer id="mcslee" name="Mark Slee"/>
@@ -176,5 +178,5 @@
     <!-- run with: ant -Drelease=true publish -->
     <signAndDeploy file="${as3.pom.xml}" packaging="pom" classifier="" pom="${as3.pom.xml}"/>
     <signAndDeploy file="${as3.swc.file}" packaging="swc" classifier="" pom="${as3.pom.xml}"/>
-  </target>	
+  </target>
 </project>
diff --git a/lib/c_glib/README.md b/lib/c_glib/README.md
index fd70d08..dd84f3d 100644
--- a/lib/c_glib/README.md
+++ b/lib/c_glib/README.md
@@ -32,3 +32,18 @@
 GLib
 http://www.gtk.org/
 
+Breaking Changes
+================
+
+0.12.0
+------
+
+The compiler's handling of namespaces when generating the name of types,
+functions and header files has been improved. This means code written to use
+classes generated by previous versions of the compiler may need to be updated to
+reflect the proper convention for class names, which is
+
+- A lowercase, [snake-case](https://en.wikipedia.org/wiki/Snake_case)
+  representation of the class' namespace, followed by
+- An underscore and
+- A lowercase, snake-case representation of the class' name.
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c
index 1433725..8296a8c 100644
--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c
@@ -465,7 +465,7 @@
       }
     case T_STRUCT:
       {
-        guint32 result = 0;
+        gint32 result = 0;
         gchar *name;
         gint16 fid;
         ThriftType ftype;
@@ -475,6 +475,10 @@
         {
           result += thrift_protocol_read_field_begin (protocol, &name, &ftype,
                                                       &fid, error);
+          if (result < 0)
+          {
+            return result;  
+          }
           if (ftype == T_STOP)
           {
             break;
@@ -487,7 +491,7 @@
       }
     case T_SET:
       {
-        guint32 result = 0;
+        gint32 result = 0;
         ThriftType elem_type;
         guint32 i, size;
         result += thrift_protocol_read_set_begin (protocol, &elem_type, &size,
@@ -501,7 +505,7 @@
       }
     case T_MAP:
       {
-        guint32 result = 0;
+        gint32 result = 0;
         ThriftType elem_type;
         ThriftType key_type;
         guint32 i, size;
@@ -517,7 +521,7 @@
       }
     case T_LIST:
       {
-        guint32 result = 0;
+        gint32 result = 0;
         ThriftType elem_type;
         guint32 i, size;
         result += thrift_protocol_read_list_begin (protocol, &elem_type, &size,
diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/testbufferedtransport.c
index c6e6b58..d01806d 100755
--- a/lib/c_glib/test/testbufferedtransport.c
+++ b/lib/c_glib/test/testbufferedtransport.c
@@ -175,11 +175,8 @@
 static void
 thrift_socket_server_open (const int port, int times)
 {
-  int bytes = 0;
   ThriftServerTransport *transport = NULL;
   ThriftTransport *client = NULL;
-  guchar buf[10]; /* a buffer */
-  guchar match[10] = TEST_DATA;
   int i;
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
 					      "port", port, NULL);
diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testframedtransport.c
index 45397ce..008e61e 100755
--- a/lib/c_glib/test/testframedtransport.c
+++ b/lib/c_glib/test/testframedtransport.c
@@ -249,11 +249,8 @@
 static void
 thrift_socket_server_open (const int port, int times)
 {
-  int bytes = 0;
   ThriftServerTransport *transport = NULL;
   ThriftTransport *client = NULL;
-  guchar buf[10]; /* a buffer */
-  guchar match[10] = TEST_DATA;
   int i;
 
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
diff --git a/lib/c_glib/test/testthrifttestclient.cpp b/lib/c_glib/test/testthrifttestclient.cpp
index 5b06883..1910c8a 100755
--- a/lib/c_glib/test/testthrifttestclient.cpp
+++ b/lib/c_glib/test/testthrifttestclient.cpp
@@ -25,7 +25,7 @@
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/protocol/TDebugProtocol.h>
 #include <thrift/server/TSimpleServer.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TServerSocket.h>
 #include "ThriftTest.h"
 #include "ThriftTest_types.h"
@@ -618,11 +618,11 @@
 
   if (pid == 0) /* child */
   {
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
-    stdcxx::shared_ptr<TestHandler> testHandler(new TestHandler());
-    stdcxx::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
-    stdcxx::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT));
-    stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TestHandler> testHandler(new TestHandler());
+    std::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
+    std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT));
+    std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
     TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory);
     signal (SIGALRM, bailout);
     alarm (60);
diff --git a/lib/c_glib/test/testtransportsocket.c b/lib/c_glib/test/testtransportsocket.c
index fedbad6..89c61b9 100755
--- a/lib/c_glib/test/testtransportsocket.c
+++ b/lib/c_glib/test/testtransportsocket.c
@@ -291,11 +291,8 @@
 static void
 thrift_socket_server_open (const int port, int times)
 {
-  int bytes = 0;
   ThriftServerTransport *transport = NULL;
   ThriftTransport *client = NULL;
-  guchar buf[10]; /* a buffer */
-  guchar match[10] = TEST_DATA;
   int i;
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
 					      "port", port, NULL);
diff --git a/lib/cl/Makefile.am b/lib/cl/Makefile.am
new file mode 100644
index 0000000..34b3886
--- /dev/null
+++ b/lib/cl/Makefile.am
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+THRIFT = $(top_builddir)/compiler/cpp/thrift
+
+all-local:
+	bash ensure-externals.sh
+
+run-tests: test/make-test-binary.lisp
+	$(SBCL) --script test/make-test-binary.lisp
+
+check-local: run-tests
+	./run-tests
+
+clean-local:
+	$(RM) run-tests quicklisp.lisp backport-update.zip
+	$(RM) -rf lib externals quicklisp
+
+EXTRA_DIST = \
+	README.md \
+	READMES \
+	load-locally.lisp \
+	test \
+	ensure-externals.sh
diff --git a/lib/cl/README.md b/lib/cl/README.md
new file mode 100644
index 0000000..1d6eafb
--- /dev/null
+++ b/lib/cl/README.md
@@ -0,0 +1,253 @@
+Thrift Common Lisp 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.
+
+
+
+Using Thrift with Common Lisp
+============================
+
+ Thrift is a protocol and library for language-independent communication between cooperating
+ processes. The communication takes the form of request and response messages, of which the forms
+ are specified in advance throufh a shared interface definition. A Thrift definition file is translated
+ into Lisp source files, which comprise several definitions:
+
+  * Three packages, one for the namespace of the implementation operators, and one each for request and
+  response operators.
+  * Various type definitions as implementations for Thrift typedef and enum definitions.
+  * DEF-STRUCT and DEF-EXCEPTION forms for Thrift struct and exception definitions.
+  * DEF-SERVICE forms for thrift service definitions.
+
+ Each service definition expands in a collection of generic function definitions. For each `op`
+ in the service definition, two functions are defined
+
+  * `op`-request is defined for use by a client. It accepts an additional initial `protocol` argument,
+    to act as the client proxy for the operation and mediate the interaction with a remote process
+    through a Thrift-encoded transport stream.
+  * `op`-response is defined for use by a server. It accepts a single `protocol` argument. A server
+    uses it to decode the request message, invoke the base `op` function with the message arguments,
+    encode and send the the result as a response, and handles exceptions.
+
+ The client interface is one operator
+
+  * `with-client (variable location) . body` : creates a connection in a dynamic context and closes it
+    upon exit. The variable is bound to a client proxy stream/protocol instance, which wraps the
+    base i/o stream - socket, file, etc, with an operators which implement the Thrift protocol
+    and transport mechanisms.
+
+ The server interface combines server and service objects
+
+  * `serve (location service)` : accepts connections on the designated port and responds to
+    requests of the service's operations.
+
+
+Building 
+--------
+
+The Thrift Common Lisp library is packaged as the ASDF[[1]] system `thrift`.
+It depends on the systems
+
+* puri[[2]] : for the thrift uri class
+* closer-mop[[3]] : for class metadata
+* trivial-utf-8[[4]] : for string codecs
+* usocket[[5]] : for the socket transport
+* ieee-floats[[6]] : for conversion between ints and floats
+* trivial-gray-streams[[7]] : an abstraction layer for gray streams
+* alexandria[[8]] : handy utilities
+
+The dependencies are bundled for local builds of tests and tutorial binaries - 
+it is possible to use those bundles to load the library, too.
+
+In order to build it, register those systems with ASDF and evaluate:
+
+    (asdf:load-system :thrift)
+
+This will compile and load the Lisp compiler for Thrift definition files, the
+transport and protocol implementations, and the client and server interface
+functions. In order to use Thrift in an application, one must also author and/or
+load the interface definitions for the remote service.[[9]] If one is implementing a service,
+one must also define the actual functions to which Thrift is to act as the proxy
+interface. The remainder of this document follows the Thrift tutorial to illustrate how
+to perform the steps
+
+  * implement the service
+  * translate the Thrift IDL
+  * load the Lisp service interfaces
+  * run a server for the service
+  * use a client to access the service remotely
+
+Note that, if one is to implement a new service, one will also need to author the
+IDL files, as there is no facility to generate them from a service implementation.
+
+
+Implement the Service
+---------------------
+
+The tutorial comprises serveral functions: `add`, `ping`, `zip`, and `calculate`.
+Each translated IDL file generates three packages for every service. In the case of
+the tutorial file, the relevant packages are:
+
+  * tutorial.calculator
+  * tutorial.calculator-implementation
+  * tutorial.calculator-response
+  
+This is to separate the request (generated), response (generated) and implementation
+(meant to be implemented by the programmer) functions for defined Thrift methods.
+
+It is suggested to work in the `tutorial-implementation` package while implementing
+the services - it imports the `common-lisp` package, while the service-specific ones
+don't (to avoid conflicts between Thrift method names and function names in `common-lisp`).
+
+    ;; define the base operations
+    
+    (in-package :tutorial-implementation)
+    
+    (defun tutorial.calculator-implementation:add (num1 num2)
+      (format t "~&Asked to add ~A and ~A." num1 num2)
+      (+ num1 num2))
+    
+    (defun tutorial.calculator-implementation:ping ()
+      (print :ping))
+    
+    (defun tutorial.calculator-implementation:zip ()
+      (print :zip))
+    
+    (defun tutorial.calculator-implementation:calculate (logid task)
+      (calculate-op (work-op task) (work-num1 task) (work-num2 task)))
+    
+    (defgeneric calculate-op (op arg1 arg2)
+      (:method :around (op arg1 arg2)
+        (let ((result (call-next-method)))
+          (format t "~&Asked to calculate: ~d on  ~A and ~A = ~d." op arg1 arg2 result)
+          result))
+    
+      (:method ((op (eql operation.add)) arg1 arg2)
+        (+ arg1 arg2))
+      (:method ((op (eql operation.subtract)) arg1 arg2)
+        (- arg1 arg2))
+      (:method ((op (eql operation.multiply)) arg1 arg2)
+        (* arg1 arg2))
+      (:method ((op (eql operation.divide)) arg1 arg2)
+        (/ arg1 arg2)))
+    
+    (defun zip () (print 'zip))
+
+
+Translate the Thrift IDL
+------------------------
+
+IDL files employ the file extension `thrift`. In this case, there are two files to translate
+  * `tutorial.thrift`
+  * `shared.thrift`
+As the former includes the latter, one uses it to generate the interfaces:
+
+    $THRIFT/bin/thrift -r --gen cl $THRIFT/tutorial/tutorial.thrift
+    
+`-r` stands for recursion, while `--gen` lets one choose the language to translate to.
+
+
+Load the Lisp translated service interfaces
+-------------------------------------------
+
+The translator generates three files for each IDL file. For example `tutorial-types.lisp`,
+`tutorial-vars.lisp` and an `.asd` file that can be used to load them both and pull in
+other includes (like `shared` within the tutorial) as dependencies.
+
+
+Run a Server for the Service
+----------------------------
+
+The actual service name, as specified in the `def-service` form in `tutorial.lisp`, is `calculator`. 
+Each service definition defines a global variable with the service name and binds it to a
+service instance whch describes the operations.
+
+In order to start a service, specify a location and the service instance. 
+
+    (in-package :tutorial)
+    (serve #u"thrift://127.0.0.1:9091" calculator)
+
+
+Use a Client to Access the Service Remotely
+-------------------------------------------
+
+
+[in some other process] run the client
+
+    (in-package :cl-user)
+
+    (macrolet ((show (form)
+                 `(format *trace-output* "~%~s =>~{ ~s~}"
+                          ',form
+                          (multiple-value-list (ignore-errors ,form)))))
+      (with-client (protocol #u"thrift://127.0.0.1:9091")
+        (show (tutorial.calculator:ping protocol))
+        (show (tutorial.calculator:add protocol 1 2))
+        (show (tutorial.calculator:add protocol 1 4))
+    
+        (let ((task (make-instance 'tutorial:work
+                      :op operation.subtract :num1 15 :num2 10)))
+          (show (tutorial.calculator:calculate protocol 1 task))
+        
+          (setf (tutorial:work-op task) operation.divide
+                (tutorial:work-num1 task) 1
+                (tutorial:work-num2 task) 0)
+          (show (tutorial.calculator:calculate protocol 1 task)))
+        
+        (show (shared.shared-service:get-struct protocol 1))
+    
+        (show (zip protocol))))
+
+Issues
+------
+
+### optional fields 
+ Where the IDL declares a field options, the def-struct form includes no
+ initform for the slot and the encoding operator skips an unbound slot. This leave some ambiguity
+ with bool fields.
+
+### instantiation protocol :
+ struct classes are standard classes and exception classes are
+ whatever the implementation prescribes. decoders apply make-struct to an initargs list.
+ particularly at the service end, there are advantages to resourcing structs and decoding
+ with direct side-effects on slot-values
+
+### maps:
+ Maps are now represented as hash tables. As data through the call/reply interface is all statically
+ typed, it is not necessary for the objects to themselves indicate the coding form. Association lists
+ would be sufficient. As the key type is arbitrary, property lists offer no additional convenience:
+ as `getf` operates with `eq` a new access interface would be necessary and they would not be
+ available for function application.
+
+
+ [1]: www.common-lisp.net/asdf
+ [2]: http://github.com/lisp/com.b9.puri.ppcre
+ [3]: www.common-lisp.net/closer-mop
+ [4]: trivial-utf-8
+ [5]: https://github.com/usocket/usocket
+ [6]: https://github.com/marijnh/ieee-floats
+ [7]: https://github.com/trivial-gray-streams/trivial-gray-streams
+ [8]: https://gitlab.common-lisp.net/alexandria/alexandria
+ [9]: http://wiki.apache.org/thrift/ThriftGeneration
+
+* usocket[[5]] : for the socket transport
+* ieee-floats[[6]] : for conversion between ints and floats
+* trivial-gray-streams[[7]] : an abstraction layer for gray streams
+* alexandria[[8]] : handy utilities
diff --git a/lib/cl/READMES/readme-cassandra.lisp b/lib/cl/READMES/readme-cassandra.lisp
new file mode 100644
index 0000000..72744ea
--- /dev/null
+++ b/lib/cl/READMES/readme-cassandra.lisp
@@ -0,0 +1,64 @@
+(in-package :cl-user)
+
+#+(or ccl sbcl) /development/source/library/
+(load "build-init.lisp")
+
+;;; ! first, select the api version in the cassandra system definition
+;;; as only one should be loaded at a time.
+(asdf:load-system :de.setf.cassandra)
+
+(in-package :de.setf.cassandra)
+
+(defparameter *c-location*
+  ;; remote
+  ;; #u"thrift://ec2-174-129-66-148.compute-1.amazonaws.com:9160"
+  ;; local
+  #u"thrift://127.0.0.1:9160"
+  "A cassandra service location - either the local one or a remote service 
+ - always a 'thrift' uri.")
+
+(defparameter *c* (thrift:client *c-location*))
+
+
+(cassandra:describe-keyspaces *c*)
+;; => ("Keyspace1" "system")
+
+(cassandra:describe-cluster-name *c*)
+;; =>"Test Cluster"
+
+(cassandra:describe-version *c*)
+;; => "2.1.0"
+
+(loop for space in (cassandra:describe-keyspaces *c*)
+      collect (loop for key being each hash-key of (cassandra:describe-keyspace *c* space)
+                    using (hash-value value)
+                    collect (cons key
+                                  (loop for key being each hash-key of value
+                                        using (hash-value value)
+                                        collect (cons key value)))))
+
+
+(close *c*)
+
+(defun describe-cassandra (location &optional (stream *standard-output*))
+  "Print the first-order store metadata for a cassandra LOCATION."
+
+  (thrift:with-client (cassandra location)
+    (let* ((keyspace-names (cassandra:describe-keyspaces cassandra))
+           (cluster (cassandra:describe-cluster-name cassandra))
+           (version (cassandra:describe-version cassandra))
+           (keyspace-descriptions (loop for space in keyspace-names
+                                        collect (cons space
+                                                      (loop for key being each hash-key
+                                                            of (cassandra:describe-keyspace cassandra space)
+                                                            using (hash-value value)
+                                                            collect (cons key
+                                                                          (loop for key being each hash-key of value
+                                                                                using (hash-value value)
+                                                                                collect (cons key value))))))))
+      (format stream "~&connection to : ~a" cassandra)
+      (format stream "~&version : ~a" version)
+      (format stream "~&cluster : ~a" cluster)
+      (format stream "~&keyspaces~{~{~%~%space: ~a~@{~%  ~{~a :~@{~20t~:w~^~%~}~}~}~}~}" keyspace-descriptions))))
+
+;;; (describe-cassandra *c-location*)
diff --git a/lib/cl/ensure-externals.sh b/lib/cl/ensure-externals.sh
new file mode 100755
index 0000000..0495f03
--- /dev/null
+++ b/lib/cl/ensure-externals.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+if [[ ! -e quicklisp.lisp ]]; then curl -O https://beta.quicklisp.org/quicklisp.lisp; fi
+sbcl --load quicklisp.lisp \
+     --eval "(ignore-errors (quicklisp-quickstart:install :path \"quicklisp/\"))" \
+     --eval "(load \"quicklisp/setup.lisp\")" \
+     --eval "(quicklisp:bundle-systems '(#:puri #:usocket #:closer-mop #:trivial-utf-8 #:ieee-floats #:trivial-gray-streams #:alexandria #:bordeaux-threads #:cl-ppcre #:fiasco #:net.didierverna.clon) :to \"externals/\")" \
+     --eval "(quit)" \
+     --no-userinit
+if [[ ! -e backport-update.zip ]]; then
+    curl -O -L https://github.com/TurtleWarePL/de.setf.thrift/archive/backport-update.zip;
+fi
+mkdir -p lib
+unzip -u backport-update.zip -d lib
diff --git a/lib/cl/load-locally.lisp b/lib/cl/load-locally.lisp
new file mode 100644
index 0000000..d12c704
--- /dev/null
+++ b/lib/cl/load-locally.lisp
@@ -0,0 +1,23 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+;;;; Just a script for loading the library itself, using bundled dependencies.
+;;;; This is here for when we want to build the self-test and cross-test
+;;;; binaries.
+
+(require "asdf")
+
+(load (merge-pathnames "externals/bundle.lisp" *load-truename*))
+(asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*))
+(asdf:load-system :thrift)
diff --git a/lib/cl/test/make-test-binary.lisp b/lib/cl/test/make-test-binary.lisp
new file mode 100644
index 0000000..4e7a58c
--- /dev/null
+++ b/lib/cl/test/make-test-binary.lisp
@@ -0,0 +1,31 @@
+;;;; Licensed 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.
+
+;;;; This file is used to build the binary that runs all self-tests. The
+;;;; binary is then meant to be hooked up to Thrift's `make check` facility,
+;;;; but can easily be run on its own as well.
+
+(in-package #:cl-user)
+
+(require "asdf")
+(load (merge-pathnames "../load-locally.lisp" *load-truename*))
+(asdf:load-asd (merge-pathnames "../lib/de.setf.thrift-backport-update/test/thrift-test.asd" *load-truename*))
+(asdf:load-system :thrift-test)
+(asdf:load-system :net.didierverna.clon)
+
+(net.didierverna.clon:nickname-package)
+
+(defun main ()
+  (let ((result (if (fiasco:run-tests 'thrift-test) 0 -1)))
+    (clon:exit result)))
+
+(clon:dump "run-tests" main)
diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h
index 89486b2..d01826d 100644
--- a/lib/cocoa/src/Thrift.h
+++ b/lib/cocoa/src/Thrift.h
@@ -17,4 +17,4 @@
  * under the License.
  */
 
-#define ThriftVersion @"0.11.0"
+#define ThriftVersion @"1.0.0"
diff --git a/lib/cocoa/src/protocol/TBase.h b/lib/cocoa/src/protocol/TBase.h
index b31061e..9935d50 100644
--- a/lib/cocoa/src/protocol/TBase.h
+++ b/lib/cocoa/src/protocol/TBase.h
@@ -26,14 +26,14 @@
 /**
  * De-serialize object from the given input protocol
  *
- * @param input protocol used for reading
+ * @param inProtocol protocol used for reading
  */
 -(BOOL) read:(id <TProtocol>)inProtocol error:(NSError **)error;
 
 /**
  * Serialize object to the given protocol
  *
- * @param buf output protocol used for writing
+ * @param outProtocol output protocol used for writing
  */
 -(BOOL) write:(id <TProtocol>)outProtocol error:(NSError **)error;
 
diff --git a/lib/cocoa/src/transport/TNSStreamTransport.m b/lib/cocoa/src/transport/TNSStreamTransport.m
index c425043..18c41d3 100644
--- a/lib/cocoa/src/transport/TNSStreamTransport.m
+++ b/lib/cocoa/src/transport/TNSStreamTransport.m
@@ -94,7 +94,7 @@
 
 -(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
 {
-  int got = 0;
+  UInt32 got = 0;
   NSInteger total = 0;
   while (got < length) {
 
diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt
index 734af72..9ea82c3 100755
--- a/lib/cpp/CMakeLists.txt
+++ b/lib/cpp/CMakeLists.txt
@@ -28,6 +28,7 @@
    src/thrift/TApplicationException.cpp
    src/thrift/TOutput.cpp
    src/thrift/async/TAsyncChannel.cpp
+   src/thrift/async/TAsyncProtocolProcessor.cpp
    src/thrift/async/TConcurrentClientSyncInfo.h
    src/thrift/async/TConcurrentClientSyncInfo.cpp
    src/thrift/concurrency/ThreadManager.cpp
@@ -102,14 +103,7 @@
 endif()
 
 # WITH_*THREADS selects which threading library to use
-if(WITH_BOOSTTHREADS)
-    set( thriftcpp_threads_SOURCES
-        src/thrift/concurrency/BoostThreadFactory.cpp
-        src/thrift/concurrency/BoostMonitor.cpp
-        src/thrift/concurrency/BoostMutex.cpp
-    )
-    list(APPEND SYSLIBS "${Boost_LIBRARIES}")
-elseif(UNIX AND NOT WITH_STDTHREADS)
+if(UNIX AND NOT WITH_STDTHREADS)
     if(ANDROID)
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
     else()
@@ -140,7 +134,6 @@
     src/thrift/server/TNonblockingServer.cpp
     src/thrift/transport/TNonblockingServerSocket.cpp
     src/thrift/transport/TNonblockingSSLServerSocket.cpp
-    src/thrift/async/TAsyncProtocolProcessor.cpp
     src/thrift/async/TEvhttpServer.cpp
     src/thrift/async/TEvhttpClientChannel.cpp
 )
diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am
index cd1d923..85bb9ab 100755
--- a/lib/cpp/Makefile.am
+++ b/lib/cpp/Makefile.am
@@ -70,6 +70,7 @@
                        src/thrift/TOutput.cpp \
                        src/thrift/VirtualProfiling.cpp \
                        src/thrift/async/TAsyncChannel.cpp \
+                       src/thrift/async/TAsyncProtocolProcessor.cpp \
                        src/thrift/async/TConcurrentClientSyncInfo.cpp \
                        src/thrift/concurrency/ThreadManager.cpp \
                        src/thrift/concurrency/TimerManager.cpp \
@@ -105,18 +106,11 @@
                        src/thrift/server/TThreadPoolServer.cpp \
                        src/thrift/server/TThreadedServer.cpp
 
-if WITH_BOOSTTHREADS
-libthrift_la_SOURCES += src/thrift/concurrency/BoostThreadFactory.cpp \
-                        src/thrift/concurrency/BoostMonitor.cpp \
-                        src/thrift/concurrency/BoostMutex.cpp
-else
 libthrift_la_SOURCES += src/thrift/concurrency/Mutex.cpp \
                         src/thrift/concurrency/Monitor.cpp \
                         src/thrift/concurrency/PosixThreadFactory.cpp
-endif
 
 libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \
-                         src/thrift/async/TAsyncProtocolProcessor.cpp \
                          src/thrift/async/TEvhttpServer.cpp \
                          src/thrift/async/TEvhttpClientChannel.cpp
 
@@ -150,7 +144,7 @@
 libthriftqt_la_CXXFLAGS  = $(AM_CXXFLAGS)
 libthriftqt5_la_CXXFLAGS  = $(AM_CXXFLAGS)
 libthriftnb_la_LDFLAGS  = -release $(VERSION) $(BOOST_LDFLAGS)
-libthriftz_la_LDFLAGS   = -release $(VERSION) $(BOOST_LDFLAGS)
+libthriftz_la_LDFLAGS   = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LIBS)
 libthriftqt_la_LDFLAGS   = -release $(VERSION) $(BOOST_LDFLAGS) $(QT_LIBS)
 libthriftqt5_la_LDFLAGS   = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS)
 
@@ -165,12 +159,10 @@
                          src/thrift/TApplicationException.h \
                          src/thrift/TLogging.h \
                          src/thrift/TToString.h \
-                         src/thrift/stdcxx.h \
                          src/thrift/TBase.h
 
 include_concurrencydir = $(include_thriftdir)/concurrency
 include_concurrency_HEADERS = \
-                         src/thrift/concurrency/BoostThreadFactory.h \
                          src/thrift/concurrency/Exception.h \
                          src/thrift/concurrency/Mutex.h \
                          src/thrift/concurrency/Monitor.h \
diff --git a/lib/cpp/libthrift.vcxproj b/lib/cpp/libthrift.vcxproj
index 307b121..d1097ec 100644
--- a/lib/cpp/libthrift.vcxproj
+++ b/lib/cpp/libthrift.vcxproj
@@ -53,12 +53,9 @@
     <ClCompile Include="src\thrift\server\TSimpleServer.cpp"/>
     <ClCompile Include="src\thrift\server\TThreadPoolServer.cpp"/>
     <ClCompile Include="src\thrift\server\TThreadedServer.cpp"/>
-	<ClCompile Include="src\thrift\server\TConnectedClient.cpp"/>
-	<ClCompile Include="src\thrift\server\TNonblockingServer.cpp"/>
-	<ClCompile Include="src\thrift\server\TServerFramework.cpp"/>
-	<ClCompile Include="src\thrift\server\TSimpleServer.cpp"/>
-	<ClCompile Include="src\thrift\server\TThreadedServer.cpp"/>
-	<ClCompile Include="src\thrift\server\TThreadPoolServer.cpp"/>
+    <ClCompile Include="src\thrift\server\TConnectedClient.cpp"/>
+    <ClCompile Include="src\thrift\server\TNonblockingServer.cpp"/>
+    <ClCompile Include="src\thrift\server\TServerFramework.cpp"/>
     <ClCompile Include="src\thrift\TApplicationException.cpp"/>
     <ClCompile Include="src\thrift\TOutput.cpp"/>
     <ClCompile Include="src\thrift\transport\TBufferTransports.cpp"/>
diff --git a/lib/cpp/src/thrift/TApplicationException.h b/lib/cpp/src/thrift/TApplicationException.h
index 81d9424..60618fb 100644
--- a/lib/cpp/src/thrift/TApplicationException.h
+++ b/lib/cpp/src/thrift/TApplicationException.h
@@ -57,7 +57,7 @@
   TApplicationException(TApplicationExceptionType type, const std::string& message)
     : TException(message), type_(type) {}
 
-  virtual ~TApplicationException() throw() {}
+  virtual ~TApplicationException() noexcept {}
 
   /**
    * Returns an error code that provides information about the type of error
@@ -67,7 +67,7 @@
    */
   TApplicationExceptionType getType() const { return type_; }
 
-  virtual const char* what() const throw() {
+  virtual const char* what() const noexcept {
     if (message_.empty()) {
       switch (type_) {
       case UNKNOWN:
diff --git a/lib/cpp/src/thrift/TDispatchProcessor.h b/lib/cpp/src/thrift/TDispatchProcessor.h
index dadc87b..28d347d 100644
--- a/lib/cpp/src/thrift/TDispatchProcessor.h
+++ b/lib/cpp/src/thrift/TDispatchProcessor.h
@@ -33,8 +33,8 @@
 template <class Protocol_>
 class TDispatchProcessorT : public TProcessor {
 public:
-  virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out,
+  virtual bool process(std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out,
                        void* connectionContext) {
     protocol::TProtocol* inRaw = in.get();
     protocol::TProtocol* outRaw = out.get();
@@ -105,8 +105,8 @@
  */
 class TDispatchProcessor : public TProcessor {
 public:
-  virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out,
+  virtual bool process(std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out,
                        void* connectionContext) {
     std::string fname;
     protocol::TMessageType mtype;
diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp
index bb46263..ae3a9e2 100644
--- a/lib/cpp/src/thrift/TOutput.cpp
+++ b/lib/cpp/src/thrift/TOutput.cpp
@@ -94,7 +94,7 @@
 }
 
 void TOutput::perror(const char* message, int errno_copy) {
-  std::string out = message + strerror_s(errno_copy);
+  std::string out = message + std::string(": ") + strerror_s(errno_copy);
   f_(out.c_str());
 }
 
diff --git a/lib/cpp/src/thrift/TProcessor.h b/lib/cpp/src/thrift/TProcessor.h
index 27294d3..6a46466 100644
--- a/lib/cpp/src/thrift/TProcessor.h
+++ b/lib/cpp/src/thrift/TProcessor.h
@@ -22,7 +22,6 @@
 
 #include <string>
 #include <thrift/protocol/TProtocol.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -142,28 +141,28 @@
 public:
   virtual ~TProcessor() {}
 
-  virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out,
+  virtual bool process(std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out,
                        void* connectionContext) = 0;
 
-  bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
+  bool process(std::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
     return process(io, io, connectionContext);
   }
 
-  stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
+  std::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
 
-  void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
+  void setEventHandler(std::shared_ptr<TProcessorEventHandler> eventHandler) {
     eventHandler_ = eventHandler;
   }
 
 protected:
   TProcessor() {}
 
-  stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
+  std::shared_ptr<TProcessorEventHandler> eventHandler_;
 };
 
 /**
- * This is a helper class to allow stdcxx::shared_ptr to be used with handler
+ * This is a helper class to allow std::shared_ptr to be used with handler
  * pointers returned by the generated handler factories.
  *
  * The handler factory classes generated by the thrift compiler return raw
@@ -177,7 +176,7 @@
 template <typename HandlerFactory_>
 class ReleaseHandler {
 public:
-  ReleaseHandler(const stdcxx::shared_ptr<HandlerFactory_>& handlerFactory)
+  ReleaseHandler(const std::shared_ptr<HandlerFactory_>& handlerFactory)
     : handlerFactory_(handlerFactory) {}
 
   void operator()(typename HandlerFactory_::Handler* handler) {
@@ -187,18 +186,18 @@
   }
 
 private:
-  stdcxx::shared_ptr<HandlerFactory_> handlerFactory_;
+  std::shared_ptr<HandlerFactory_> handlerFactory_;
 };
 
 struct TConnectionInfo {
   // The input and output protocols
-  stdcxx::shared_ptr<protocol::TProtocol> input;
-  stdcxx::shared_ptr<protocol::TProtocol> output;
+  std::shared_ptr<protocol::TProtocol> input;
+  std::shared_ptr<protocol::TProtocol> output;
   // The underlying transport used for the connection
   // This is the transport that was returned by TServerTransport::accept(),
   // and it may be different than the transport pointed to by the input and
   // output protocols.
-  stdcxx::shared_ptr<transport::TTransport> transport;
+  std::shared_ptr<transport::TTransport> transport;
 };
 
 class TProcessorFactory {
@@ -212,17 +211,17 @@
    * accepted on.  This generally means that this call does not need to be
    * thread safe, as it will always be invoked from a single thread.
    */
-  virtual stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
+  virtual std::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
 };
 
 class TSingletonProcessorFactory : public TProcessorFactory {
 public:
-  TSingletonProcessorFactory(stdcxx::shared_ptr<TProcessor> processor) : processor_(processor) {}
+  TSingletonProcessorFactory(std::shared_ptr<TProcessor> processor) : processor_(processor) {}
 
-  stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
+  std::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
 
 private:
-  stdcxx::shared_ptr<TProcessor> processor_;
+  std::shared_ptr<TProcessor> processor_;
 };
 }
 } // apache::thrift
diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h
index e8e70eb..6322742 100644
--- a/lib/cpp/src/thrift/Thrift.h
+++ b/lib/cpp/src/thrift/Thrift.h
@@ -42,9 +42,6 @@
 #include <exception>
 #include <typeinfo>
 
-#include <boost/utility/enable_if.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-
 #include <thrift/TLogging.h>
 #include <thrift/TOutput.h>
 
@@ -82,9 +79,9 @@
 
   TException(const std::string& message) : message_(message) {}
 
-  virtual ~TException() throw() {}
+  virtual ~TException() noexcept {}
 
-  virtual const char* what() const throw() {
+  virtual const char* what() const noexcept {
     if (message_.empty()) {
       return "Default TException.";
     } else {
diff --git a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h
index 0d56c78..9c96b14 100644
--- a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h
+++ b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_
 #define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TBufferTransports.h>
 
 namespace apache {
@@ -34,9 +34,9 @@
   // forcefully close the connection (if applicable).
   // "in" and "out" should be TMemoryBuffer or similar,
   // not a wrapper around a socket.
-  virtual void process(stdcxx::function<void(bool healthy)> _return,
-                       stdcxx::shared_ptr<transport::TBufferBase> ibuf,
-                       stdcxx::shared_ptr<transport::TBufferBase> obuf) = 0;
+  virtual void process(std::function<void(bool healthy)> _return,
+                       std::shared_ptr<transport::TBufferBase> ibuf,
+                       std::shared_ptr<transport::TBufferBase> obuf) = 0;
   virtual ~TAsyncBufferProcessor() {}
 };
 }
diff --git a/lib/cpp/src/thrift/async/TAsyncChannel.cpp b/lib/cpp/src/thrift/async/TAsyncChannel.cpp
index c87659f..01b9113 100644
--- a/lib/cpp/src/thrift/async/TAsyncChannel.cpp
+++ b/lib/cpp/src/thrift/async/TAsyncChannel.cpp
@@ -18,7 +18,6 @@
  */
 
 #include <thrift/async/TAsyncChannel.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -27,8 +26,8 @@
 void TAsyncChannel::sendAndRecvMessage(const VoidCallback& cob,
                                        TMemoryBuffer* sendBuf,
                                        TMemoryBuffer* recvBuf) {
-  apache::thrift::stdcxx::function<void()> send_done
-      = apache::thrift::stdcxx::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf);
+  std::function<void()> send_done
+      = std::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf);
 
   sendMessage(send_done, sendBuf);
 }
diff --git a/lib/cpp/src/thrift/async/TAsyncChannel.h b/lib/cpp/src/thrift/async/TAsyncChannel.h
index f8d2b03..d7ace96 100644
--- a/lib/cpp/src/thrift/async/TAsyncChannel.h
+++ b/lib/cpp/src/thrift/async/TAsyncChannel.h
@@ -20,7 +20,8 @@
 #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_
 #define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <functional>
+#include <memory>
 #include <thrift/Thrift.h>
 
 namespace apache {
@@ -38,7 +39,7 @@
 
 class TAsyncChannel {
 public:
-  typedef apache::thrift::stdcxx::function<void()> VoidCallback;
+  typedef std::function<void()> VoidCallback;
 
   virtual ~TAsyncChannel() {}
 
diff --git a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h
index a1450f0..59db597 100644
--- a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h
+++ b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h
@@ -34,9 +34,9 @@
 template <class Protocol_>
 class TAsyncDispatchProcessorT : public TAsyncProcessor {
 public:
-  virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
-                       stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out) {
+  virtual void process(std::function<void(bool success)> _return,
+                       std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out) {
     protocol::TProtocol* inRaw = in.get();
     protocol::TProtocol* outRaw = out.get();
 
@@ -70,7 +70,7 @@
     return this->dispatchCall(_return, inRaw, outRaw, fname, seqid);
   }
 
-  void processFast(apache::thrift::stdcxx::function<void(bool success)> _return,
+  void processFast(std::function<void(bool success)> _return,
                    Protocol_* in,
                    Protocol_* out) {
     std::string fname;
@@ -87,13 +87,13 @@
     return this->dispatchCallTemplated(_return, in, out, fname, seqid);
   }
 
-  virtual void dispatchCall(apache::thrift::stdcxx::function<void(bool ok)> _return,
+  virtual void dispatchCall(std::function<void(bool ok)> _return,
                             apache::thrift::protocol::TProtocol* in,
                             apache::thrift::protocol::TProtocol* out,
                             const std::string& fname,
                             int32_t seqid) = 0;
 
-  virtual void dispatchCallTemplated(apache::thrift::stdcxx::function<void(bool ok)> _return,
+  virtual void dispatchCallTemplated(std::function<void(bool ok)> _return,
                                      Protocol_* in,
                                      Protocol_* out,
                                      const std::string& fname,
@@ -106,9 +106,9 @@
  */
 class TAsyncDispatchProcessor : public TAsyncProcessor {
 public:
-  virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
-                       stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out) {
+  virtual void process(std::function<void(bool success)> _return,
+                       std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out) {
     protocol::TProtocol* inRaw = in.get();
     protocol::TProtocol* outRaw = out.get();
 
@@ -131,7 +131,7 @@
     return dispatchCall(_return, inRaw, outRaw, fname, seqid);
   }
 
-  virtual void dispatchCall(apache::thrift::stdcxx::function<void(bool ok)> _return,
+  virtual void dispatchCall(std::function<void(bool ok)> _return,
                             apache::thrift::protocol::TProtocol* in,
                             apache::thrift::protocol::TProtocol* out,
                             const std::string& fname,
diff --git a/lib/cpp/src/thrift/async/TAsyncProcessor.h b/lib/cpp/src/thrift/async/TAsyncProcessor.h
index afc4ffa..fdb976d 100644
--- a/lib/cpp/src/thrift/async/TAsyncProcessor.h
+++ b/lib/cpp/src/thrift/async/TAsyncProcessor.h
@@ -21,7 +21,7 @@
 #define _THRIFT_TASYNCPROCESSOR_H_ 1
 
 #include <thrift/protocol/TProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/TProcessor.h>
 
 namespace apache {
@@ -37,25 +37,25 @@
 public:
   virtual ~TAsyncProcessor() {}
 
-  virtual void process(stdcxx::function<void(bool success)> _return,
-                       stdcxx::shared_ptr<protocol::TProtocol> in,
-                       stdcxx::shared_ptr<protocol::TProtocol> out) = 0;
+  virtual void process(std::function<void(bool success)> _return,
+                       std::shared_ptr<protocol::TProtocol> in,
+                       std::shared_ptr<protocol::TProtocol> out) = 0;
 
-  void process(stdcxx::function<void(bool success)> _return,
-               stdcxx::shared_ptr<protocol::TProtocol> io) {
+  void process(std::function<void(bool success)> _return,
+               std::shared_ptr<protocol::TProtocol> io) {
     return process(_return, io, io);
   }
 
-  stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
+  std::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
 
-  void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
+  void setEventHandler(std::shared_ptr<TProcessorEventHandler> eventHandler) {
     eventHandler_ = eventHandler;
   }
 
 protected:
   TAsyncProcessor() {}
 
-  stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
+  std::shared_ptr<TProcessorEventHandler> eventHandler_;
 };
 
 class TAsyncProcessorFactory {
@@ -69,7 +69,7 @@
    * accepted on.  This generally means that this call does not need to be
    * thread safe, as it will always be invoked from a single thread.
    */
-  virtual stdcxx::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
+  virtual std::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp
index b9ffb04..cb5201b 100644
--- a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp
+++ b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp
@@ -26,23 +26,23 @@
 namespace thrift {
 namespace async {
 
-void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
-                                      stdcxx::shared_ptr<TBufferBase> ibuf,
-                                      stdcxx::shared_ptr<TBufferBase> obuf) {
-  stdcxx::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
-  stdcxx::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
+void TAsyncProtocolProcessor::process(std::function<void(bool healthy)> _return,
+                                      std::shared_ptr<TBufferBase> ibuf,
+                                      std::shared_ptr<TBufferBase> obuf) {
+  std::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
+  std::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
   return underlying_
-      ->process(apache::thrift::stdcxx::bind(&TAsyncProtocolProcessor::finish,
+      ->process(std::bind(&TAsyncProtocolProcessor::finish,
                                              _return,
                                              oprot,
-                                             apache::thrift::stdcxx::placeholders::_1),
+                                             std::placeholders::_1),
                 iprot,
                 oprot);
 }
 
 /* static */ void TAsyncProtocolProcessor::finish(
-    apache::thrift::stdcxx::function<void(bool healthy)> _return,
-    stdcxx::shared_ptr<TProtocol> oprot,
+    std::function<void(bool healthy)> _return,
+    std::shared_ptr<TProtocol> oprot,
     bool healthy) {
   (void)oprot;
   // This is a stub function to hold a reference to oprot.
diff --git a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h
index ce3883c..8052cf3 100644
--- a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h
+++ b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h
@@ -30,23 +30,23 @@
 
 class TAsyncProtocolProcessor : public TAsyncBufferProcessor {
 public:
-  TAsyncProtocolProcessor(stdcxx::shared_ptr<TAsyncProcessor> underlying,
-                          stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
+  TAsyncProtocolProcessor(std::shared_ptr<TAsyncProcessor> underlying,
+                          std::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
     : underlying_(underlying), pfact_(pfact) {}
 
-  virtual void process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
-                       stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
-                       stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
+  virtual void process(std::function<void(bool healthy)> _return,
+                       std::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
+                       std::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
 
   virtual ~TAsyncProtocolProcessor() {}
 
 private:
-  static void finish(apache::thrift::stdcxx::function<void(bool healthy)> _return,
-                     stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
+  static void finish(std::function<void(bool healthy)> _return,
+                     std::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
                      bool healthy);
 
-  stdcxx::shared_ptr<TAsyncProcessor> underlying_;
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
+  std::shared_ptr<TAsyncProcessor> underlying_;
+  std::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h
index 9ec77b9..0bc5eb5 100644
--- a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h
+++ b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h
@@ -22,7 +22,7 @@
 #include <thrift/protocol/TProtocol.h>
 #include <thrift/concurrency/Mutex.h>
 #include <thrift/concurrency/Monitor.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <vector>
 #include <string>
 #include <map>
@@ -60,7 +60,7 @@
 
 class TConcurrentClientSyncInfo {
 private: // typedefs
-  typedef stdcxx::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
+  typedef std::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
   typedef std::map<int32_t, MonitorPtr> MonitorMap;
 
 public:
diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp
index 74acfaa..6af8104 100644
--- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp
+++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp
@@ -38,13 +38,14 @@
                                            const std::string& path,
                                            const char* address,
                                            int port,
-                                           struct event_base* eb)
+                                           struct event_base* eb,
+                                           struct evdns_base* dnsbase)
+
   : host_(host), path_(path), conn_(NULL) {
-  conn_ = evhttp_connection_new(address, port);
+  conn_ = evhttp_connection_base_new(eb, dnsbase, address, port);
   if (conn_ == NULL) {
     throw TException("evhttp_connection_new failed");
   }
-  evhttp_connection_set_base(conn_, eb);
 }
 
 TEvhttpClientChannel::~TEvhttpClientChannel() {
diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h
index 9774952..a321f41 100644
--- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h
+++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h
@@ -23,10 +23,11 @@
 #include <queue>
 #include <string>
 #include <utility>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/async/TAsyncChannel.h>
 
 struct event_base;
+struct evdns_base;
 struct evhttp_connection;
 struct evhttp_request;
 
@@ -50,7 +51,8 @@
                        const std::string& path,
                        const char* address,
                        int port,
-                       struct event_base* eb);
+                       struct event_base* eb,
+                       struct evdns_base *dnsbase = 0);
   ~TEvhttpClientChannel();
 
   virtual void sendAndRecvMessage(const VoidCallback& cob,
diff --git a/lib/cpp/src/thrift/async/TEvhttpServer.cpp b/lib/cpp/src/thrift/async/TEvhttpServer.cpp
index d87e507..bdc3266 100644
--- a/lib/cpp/src/thrift/async/TEvhttpServer.cpp
+++ b/lib/cpp/src/thrift/async/TEvhttpServer.cpp
@@ -20,7 +20,7 @@
 #include <thrift/async/TEvhttpServer.h>
 #include <thrift/async/TAsyncBufferProcessor.h>
 #include <thrift/transport/TBufferTransports.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <evhttp.h>
 #include <event2/buffer.h>
 #include <event2/buffer_compat.h>
@@ -31,8 +31,7 @@
 #endif
 
 using apache::thrift::transport::TMemoryBuffer;
-using apache::thrift::stdcxx::scoped_ptr;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 
 namespace apache {
 namespace thrift {
@@ -40,17 +39,17 @@
 
 struct TEvhttpServer::RequestContext {
   struct evhttp_request* req;
-  stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
-  stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
+  std::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
+  std::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
 
   RequestContext(struct evhttp_request* req);
 };
 
-TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor)
+TEvhttpServer::TEvhttpServer(std::shared_ptr<TAsyncBufferProcessor> processor)
   : processor_(processor), eb_(NULL), eh_(NULL) {
 }
 
-TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port)
+TEvhttpServer::TEvhttpServer(std::shared_ptr<TAsyncBufferProcessor> processor, int port)
   : processor_(processor), eb_(NULL), eh_(NULL) {
   // Create event_base and evhttp.
   eb_ = event_base_new();
@@ -110,17 +109,17 @@
 
 void TEvhttpServer::process(struct evhttp_request* req) {
   RequestContext* ctx = new RequestContext(req);
-  return processor_->process(apache::thrift::stdcxx::bind(&TEvhttpServer::complete,
+  return processor_->process(std::bind(&TEvhttpServer::complete,
                                                           this,
                                                           ctx,
-                                                          apache::thrift::stdcxx::placeholders::_1),
+                                                          std::placeholders::_1),
                              ctx->ibuf,
                              ctx->obuf);
 }
 
 void TEvhttpServer::complete(RequestContext* ctx, bool success) {
   (void)success;
-  scoped_ptr<RequestContext> ptr(ctx);
+  std::unique_ptr<RequestContext> ptr(ctx);
 
   int code = success ? 200 : 400;
   const char* reason = success ? "OK" : "Bad Request";
diff --git a/lib/cpp/src/thrift/async/TEvhttpServer.h b/lib/cpp/src/thrift/async/TEvhttpServer.h
index afc679c..c5bf3b6 100644
--- a/lib/cpp/src/thrift/async/TEvhttpServer.h
+++ b/lib/cpp/src/thrift/async/TEvhttpServer.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_TEVHTTP_SERVER_H_
 #define _THRIFT_TEVHTTP_SERVER_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 struct event_base;
 struct evhttp;
@@ -41,14 +41,14 @@
    * address of the server as the extra arg.
    * Do not call "serve" on this server.
    */
-  TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor);
+  TEvhttpServer(std::shared_ptr<TAsyncBufferProcessor> processor);
 
   /**
    * Create a TEvhttpServer with an embedded event_base and evhttp,
    * listening on port and responding on the endpoint "/".
    * Call "serve" on this server to serve forever.
    */
-  TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port);
+  TEvhttpServer(std::shared_ptr<TAsyncBufferProcessor> processor, int port);
 
   ~TEvhttpServer();
 
@@ -63,7 +63,7 @@
   void process(struct evhttp_request* req);
   void complete(RequestContext* ctx, bool success);
 
-  stdcxx::shared_ptr<TAsyncBufferProcessor> processor_;
+  std::shared_ptr<TAsyncBufferProcessor> processor_;
   struct event_base* eb_;
   struct evhttp* eh_;
 };
diff --git a/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp b/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp
deleted file mode 100644
index ebfa0b9..0000000
--- a/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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.
- */
-
-#include <thrift/thrift-config.h>
-
-#include <thrift/concurrency/Monitor.h>
-#include <thrift/concurrency/Exception.h>
-#include <thrift/concurrency/Util.h>
-#include <thrift/transport/PlatformSocket.h>
-#include <thrift/stdcxx.h>
-
-#include <assert.h>
-#include <boost/thread.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-namespace apache {
-namespace thrift {
-namespace concurrency {
-
-/**
- * Monitor implementation using the boost thread library
- *
- * @version $Id:$
- */
-class Monitor::Impl : public boost::condition_variable_any {
-
-public:
-  Impl() : ownedMutex_(new Mutex()), mutex_(NULL) { init(ownedMutex_.get()); }
-
-  Impl(Mutex* mutex) : mutex_(NULL) { init(mutex); }
-
-  Impl(Monitor* monitor) : mutex_(NULL) { init(&(monitor->mutex())); }
-
-  Mutex& mutex() { return *mutex_; }
-  void lock() { mutex().lock(); }
-  void unlock() { mutex().unlock(); }
-
-  /**
-   * Exception-throwing version of waitForTimeRelative(), called simply
-   * wait(int64) for historical reasons.  Timeout is in milliseconds.
-   *
-   * If the condition occurs,  this function returns cleanly; on timeout or
-   * error an exception is thrown.
-   */
-  void wait(int64_t timeout_ms) {
-    int result = waitForTimeRelative(timeout_ms);
-    if (result == THRIFT_ETIMEDOUT) {
-      throw TimedOutException();
-    } else if (result != 0) {
-      throw TException("Monitor::wait() failed");
-    }
-  }
-
-  /**
-   * Waits until the specified timeout in milliseconds for the condition to
-   * occur, or waits forever if timeout_ms == 0.
-   *
-   * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
-   */
-  int waitForTimeRelative(int64_t timeout_ms) {
-    if (timeout_ms == 0LL) {
-      return waitForever();
-    }
-
-    assert(mutex_);
-    boost::timed_mutex* mutexImpl
-        = reinterpret_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
-    assert(mutexImpl);
-
-    boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
-    int res
-        = timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(timeout_ms))
-              ? 0
-              : THRIFT_ETIMEDOUT;
-    lock.release();
-    return res;
-  }
-
-  /**
-   * Waits until the absolute time specified using struct THRIFT_TIMESPEC.
-   * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
-   */
-  int waitForTime(const THRIFT_TIMESPEC* abstime) {
-    struct timeval temp;
-    temp.tv_sec = static_cast<long>(abstime->tv_sec);
-    temp.tv_usec = static_cast<long>(abstime->tv_nsec) / 1000;
-    return waitForTime(&temp);
-  }
-
-  /**
-   * Waits until the absolute time specified using struct timeval.
-   * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
-   */
-  int waitForTime(const struct timeval* abstime) {
-    assert(mutex_);
-    boost::timed_mutex* mutexImpl = static_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
-    assert(mutexImpl);
-
-    struct timeval currenttime;
-    Util::toTimeval(currenttime, Util::currentTime());
-
-    long tv_sec = static_cast<long>(abstime->tv_sec - currenttime.tv_sec);
-    long tv_usec = static_cast<long>(abstime->tv_usec - currenttime.tv_usec);
-    if (tv_sec < 0)
-      tv_sec = 0;
-    if (tv_usec < 0)
-      tv_usec = 0;
-
-    boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
-    int res = timed_wait(lock,
-                         boost::get_system_time() + boost::posix_time::seconds(tv_sec)
-                         + boost::posix_time::microseconds(tv_usec))
-                  ? 0
-                  : THRIFT_ETIMEDOUT;
-    lock.release();
-    return res;
-  }
-
-  /**
-   * Waits forever until the condition occurs.
-   * Returns 0 if condition occurs, or an error code otherwise.
-   */
-  int waitForever() {
-    assert(mutex_);
-    boost::timed_mutex* mutexImpl
-        = reinterpret_cast<boost::timed_mutex*>(mutex_->getUnderlyingImpl());
-    assert(mutexImpl);
-
-    boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
-    ((boost::condition_variable_any*)this)->wait(lock);
-    lock.release();
-    return 0;
-  }
-
-  void notify() { notify_one(); }
-
-  void notifyAll() { notify_all(); }
-
-private:
-  void init(Mutex* mutex) { mutex_ = mutex; }
-
-  stdcxx::scoped_ptr<Mutex> ownedMutex_;
-  Mutex* mutex_;
-};
-
-Monitor::Monitor() : impl_(new Monitor::Impl()) {
-}
-Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {
-}
-Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {
-}
-
-Monitor::~Monitor() {
-  delete impl_;
-}
-
-Mutex& Monitor::mutex() const {
-  return const_cast<Monitor::Impl*>(impl_)->mutex();
-}
-
-void Monitor::lock() const {
-  const_cast<Monitor::Impl*>(impl_)->lock();
-}
-
-void Monitor::unlock() const {
-  const_cast<Monitor::Impl*>(impl_)->unlock();
-}
-
-void Monitor::wait(int64_t timeout) const {
-  const_cast<Monitor::Impl*>(impl_)->wait(timeout);
-}
-
-int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const {
-  return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
-}
-
-int Monitor::waitForTime(const timeval* abstime) const {
-  return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
-}
-
-int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
-  return const_cast<Monitor::Impl*>(impl_)->waitForTimeRelative(timeout_ms);
-}
-
-int Monitor::waitForever() const {
-  return const_cast<Monitor::Impl*>(impl_)->waitForever();
-}
-
-void Monitor::notify() const {
-  const_cast<Monitor::Impl*>(impl_)->notify();
-}
-
-void Monitor::notifyAll() const {
-  const_cast<Monitor::Impl*>(impl_)->notifyAll();
-}
-}
-}
-} // apache::thrift::concurrency
diff --git a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp b/lib/cpp/src/thrift/concurrency/BoostMutex.cpp
deleted file mode 100644
index 4e556df..0000000
--- a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-#include <thrift/thrift-config.h>
-
-#include <thrift/concurrency/Mutex.h>
-#include <thrift/concurrency/Util.h>
-#include <thrift/Thrift.h>
-
-#include <cassert>
-#include <boost/thread.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-namespace apache {
-namespace thrift {
-namespace concurrency {
-
-/**
- * Implementation of Mutex class using boost::timed_mutex
- *
- * Methods throw boost::lock_error on error.
- *
- * @version $Id:$
- */
-class Mutex::impl : public boost::timed_mutex {};
-
-Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {
-  THRIFT_UNUSED_VARIABLE(init);
-}
-
-void* Mutex::getUnderlyingImpl() const {
-  return impl_.get();
-}
-
-void Mutex::lock() const {
-  impl_->lock();
-}
-
-bool Mutex::trylock() const {
-  return impl_->try_lock();
-}
-
-bool Mutex::timedlock(int64_t ms) const {
-  return impl_->timed_lock(boost::get_system_time() + boost::posix_time::milliseconds(ms));
-}
-
-void Mutex::unlock() const {
-  impl_->unlock();
-}
-
-void Mutex::DEFAULT_INITIALIZER(void* arg) {
-  THRIFT_UNUSED_VARIABLE(arg);
-}
-}
-}
-} // apache::thrift::concurrency
diff --git a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp
deleted file mode 100644
index d7d8d54..0000000
--- a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.
- */
-
-#include <thrift/thrift-config.h>
-
-#if USE_BOOST_THREAD
-
-#include <thrift/concurrency/BoostThreadFactory.h>
-#include <thrift/concurrency/Exception.h>
-#include <thrift/stdcxx.h>
-#include <cassert>
-
-#include <boost/thread.hpp>
-
-namespace apache {
-namespace thrift {
-
-using stdcxx::bind;
-using stdcxx::scoped_ptr;
-using stdcxx::shared_ptr;
-using stdcxx::weak_ptr;
-
-namespace concurrency {
-
-/**
- * The boost thread class.
- *
- * @version $Id:$
- */
-class BoostThread : public Thread {
-public:
-  enum STATE { uninitialized, starting, started, stopping, stopped };
-
-  static void* threadMain(void* arg);
-
-private:
-  scoped_ptr<boost::thread> thread_;
-  Monitor monitor_;
-  STATE state_;
-  weak_ptr<BoostThread> self_;
-  bool detached_;
-
-public:
-  BoostThread(bool detached, shared_ptr<Runnable> runnable)
-    : state_(uninitialized), detached_(detached) {
-    this->Thread::runnable(runnable);
-  }
-
-  ~BoostThread() {
-    if (!detached_ && thread_->joinable()) {
-      try {
-        join();
-      } catch (...) {
-        // We're really hosed.
-      }
-    }
-  }
-
-  STATE getState() const
-  {
-    Synchronized sync(monitor_);
-    return state_;
-  }
-
-  void setState(STATE newState)
-  {
-    Synchronized sync(monitor_);
-    state_ = newState;
-
-    // unblock start() with the knowledge that the thread has actually
-    // started running, which avoids a race in detached threads.
-    if (newState == started) {
-	  monitor_.notify();
-    }
-  }
-
-  void start() {
-    // Create reference
-    shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
-    *selfRef = self_.lock();
-
-    setState(starting);
-
-	Synchronized sync(monitor_);
-	
-    thread_.reset(new boost::thread(bind(threadMain, (void*)selfRef)));
-
-    if (detached_)
-      thread_->detach();
-    
-    // Wait for the thread to start and get far enough to grab everything
-    // that it needs from the calling context, thus absolving the caller
-    // from being required to hold on to runnable indefinitely.
-    monitor_.wait();
-  }
-
-  void join() {
-    if (!detached_ && getState() != uninitialized) {
-      thread_->join();
-    }
-  }
-
-  Thread::id_t getId() { return thread_.get() ? thread_->get_id() : boost::thread::id(); }
-
-  shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
-
-  void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }
-
-  void weakRef(shared_ptr<BoostThread> self) {
-    assert(self.get() == this);
-    self_ = weak_ptr<BoostThread>(self);
-  }
-};
-
-void* BoostThread::threadMain(void* arg) {
-  shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
-  delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);
-
-  thread->setState(started);
-  thread->runnable()->run();
-
-  if (thread->getState() != stopping && thread->getState() != stopped) {
-    thread->setState(stopping);
-  }
-  return (void*)0;
-}
-
-BoostThreadFactory::BoostThreadFactory(bool detached)
-  : ThreadFactory(detached) {
-}
-
-shared_ptr<Thread> BoostThreadFactory::newThread(shared_ptr<Runnable> runnable) const {
-  shared_ptr<BoostThread> result = shared_ptr<BoostThread>(new BoostThread(isDetached(), runnable));
-  result->weakRef(result);
-  runnable->thread(result);
-  return result;
-}
-
-Thread::id_t BoostThreadFactory::getCurrentThreadId() const {
-  return boost::this_thread::get_id();
-}
-}
-}
-} // apache::thrift::concurrency
-
-#endif // USE_BOOST_THREAD
diff --git a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h b/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h
deleted file mode 100644
index bf11a70..0000000
--- a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_
-#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1
-
-#include <thrift/concurrency/Monitor.h>
-#include <thrift/concurrency/Thread.h>
-#include <thrift/stdcxx.h>
-
-namespace apache {
-namespace thrift {
-namespace concurrency {
-
-/**
- * A thread factory to create posix threads
- *
- * @version $Id:$
- */
-class BoostThreadFactory : public ThreadFactory {
-
-public:
-  /**
-   * Boost thread factory.  All threads created by a factory are reference-counted
-   * via stdcxx::shared_ptr.  The factory guarantees that threads and the Runnable tasks they
-   * host will be properly cleaned up once the last strong reference to both is given up.
-   *
-   * Threads are created with the specified boost policy, priority, stack-size. A detachable thread
-   * is not joinable.
-   *
-   * By default threads are not joinable.
-   */
-
-  BoostThreadFactory(bool detached = true);
-
-  // From ThreadFactory;
-  stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
-
-  // From ThreadFactory;
-  Thread::id_t getCurrentThreadId() const;
-};
-
-}
-}
-} // apache::thrift::concurrency
-
-#endif // #ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_
diff --git a/lib/cpp/src/thrift/concurrency/FunctionRunner.h b/lib/cpp/src/thrift/concurrency/FunctionRunner.h
index eabf019..8ad176e 100644
--- a/lib/cpp/src/thrift/concurrency/FunctionRunner.h
+++ b/lib/cpp/src/thrift/concurrency/FunctionRunner.h
@@ -21,7 +21,7 @@
 #define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1
 
 #include <thrift/concurrency/Thread.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -44,7 +44,7 @@
  *  A* a = new A();
  *  // To create a thread that executes a.foo() every 100 milliseconds:
  *  factory->newThread(FunctionRunner::create(
- *    apache::thrift::stdcxx::bind(&A::foo, a), 100))->start();
+ *    std::bind(&A::foo, a), 100))->start();
  *
  */
 
@@ -53,20 +53,20 @@
   // This is the type of callback 'pthread_create()' expects.
   typedef void* (*PthreadFuncPtr)(void* arg);
   // This a fully-generic void(void) callback for custom bindings.
-  typedef stdcxx::function<void()> VoidFunc;
+  typedef std::function<void()> VoidFunc;
 
-  typedef stdcxx::function<bool()> BoolFunc;
+  typedef std::function<bool()> BoolFunc;
 
   /**
    * Syntactic sugar to make it easier to create new FunctionRunner
    * objects wrapped in shared_ptr.
    */
-  static stdcxx::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
-    return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
+  static std::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
+    return std::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
   }
 
-  static stdcxx::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
-    return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
+  static std::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
+    return std::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
   }
 
 private:
@@ -81,7 +81,7 @@
    * execute the given callback.  Note that the 'void*' return value is ignored.
    */
   FunctionRunner(PthreadFuncPtr func, void* arg)
-    : func_(stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
+    : func_(std::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
 
   /**
    * Given a generic callback, this FunctionRunner will execute it.
diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp
index af4fcd0..9570cc6 100644
--- a/lib/cpp/src/thrift/concurrency/Monitor.cpp
+++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp
@@ -23,7 +23,7 @@
 #include <thrift/concurrency/Exception.h>
 #include <thrift/concurrency/Util.h>
 #include <thrift/transport/PlatformSocket.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <assert.h>
 
@@ -34,8 +34,8 @@
 namespace apache {
 namespace thrift {
 
-using stdcxx::scoped_ptr;
-using stdcxx::shared_ptr;
+using std::unique_ptr;
+using std::shared_ptr;
 
 namespace concurrency {
 
@@ -163,7 +163,7 @@
     }
   }
 
-  scoped_ptr<Mutex> ownedMutex_;
+  unique_ptr<Mutex> ownedMutex_;
   Mutex* mutex_;
 
   mutable pthread_cond_t pthread_cond_;
diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h
index 09b938e..a1f5396 100644
--- a/lib/cpp/src/thrift/concurrency/Mutex.h
+++ b/lib/cpp/src/thrift/concurrency/Mutex.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_CONCURRENCY_MUTEX_H_
 #define _THRIFT_CONCURRENCY_MUTEX_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <boost/noncopyable.hpp>
 #include <stdint.h>
 
@@ -86,7 +86,7 @@
 
 private:
   class impl;
-  stdcxx::shared_ptr<impl> impl_;
+  std::shared_ptr<impl> impl_;
 };
 
 class ReadWriteMutex {
@@ -107,7 +107,7 @@
 
 private:
   class impl;
-  stdcxx::shared_ptr<impl> impl_;
+  std::shared_ptr<impl> impl_;
 };
 
 /**
diff --git a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h b/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h
index 545b572..99b4403 100644
--- a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h
+++ b/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h
@@ -22,9 +22,7 @@
 
 // clang-format off
 #include <thrift/thrift-config.h>
-#if USE_BOOST_THREAD
-#  include <thrift/concurrency/BoostThreadFactory.h>
-#elif USE_STD_THREAD
+#if USE_STD_THREAD
 #  include <thrift/concurrency/StdThreadFactory.h>
 #else
 #  include <thrift/concurrency/PosixThreadFactory.h>
@@ -36,9 +34,7 @@
 namespace concurrency {
 
 // clang-format off
-#if USE_BOOST_THREAD
-  typedef BoostThreadFactory PlatformThreadFactory;
-#elif USE_STD_THREAD
+#if USE_STD_THREAD
   typedef StdThreadFactory PlatformThreadFactory;
 #else
   typedef PosixThreadFactory PlatformThreadFactory;
diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp
index 2e35446..5c59269 100644
--- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp
+++ b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp
@@ -32,7 +32,7 @@
 
 #include <iostream>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -58,7 +58,7 @@
   int policy_;
   int priority_;
   int stackSize_;
-  stdcxx::weak_ptr<PthreadThread> self_;
+  std::weak_ptr<PthreadThread> self_;
   bool detached_;
 
 public:
@@ -66,7 +66,7 @@
                 int priority,
                 int stackSize,
                 bool detached,
-                stdcxx::shared_ptr<Runnable> runnable)
+                std::shared_ptr<Runnable> runnable)
     :
 
 #ifndef _WIN32
@@ -155,7 +155,7 @@
     }
 
     // Create reference
-    stdcxx::shared_ptr<PthreadThread>* selfRef = new stdcxx::shared_ptr<PthreadThread>();
+    std::shared_ptr<PthreadThread>* selfRef = new std::shared_ptr<PthreadThread>();
     *selfRef = self_.lock();
 
     setState(starting);
@@ -201,19 +201,19 @@
 #endif // _WIN32
   }
 
-  stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
+  std::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
 
-  void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
+  void runnable(std::shared_ptr<Runnable> value) { Thread::runnable(value); }
 
-  void weakRef(stdcxx::shared_ptr<PthreadThread> self) {
+  void weakRef(std::shared_ptr<PthreadThread> self) {
     assert(self.get() == this);
-    self_ = stdcxx::weak_ptr<PthreadThread>(self);
+    self_ = std::weak_ptr<PthreadThread>(self);
   }
 };
 
 void* PthreadThread::threadMain(void* arg) {
-  stdcxx::shared_ptr<PthreadThread> thread = *(stdcxx::shared_ptr<PthreadThread>*)arg;
-  delete reinterpret_cast<stdcxx::shared_ptr<PthreadThread>*>(arg);
+  std::shared_ptr<PthreadThread> thread = *(std::shared_ptr<PthreadThread>*)arg;
+  delete reinterpret_cast<std::shared_ptr<PthreadThread>*>(arg);
 
 #if GOOGLE_PERFTOOLS_REGISTER_THREAD
   ProfilerRegisterThread();
@@ -294,9 +294,9 @@
     stackSize_(1) {
 }
 
-stdcxx::shared_ptr<Thread> PosixThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
-  stdcxx::shared_ptr<PthreadThread> result
-      = stdcxx::shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
+std::shared_ptr<Thread> PosixThreadFactory::newThread(std::shared_ptr<Runnable> runnable) const {
+  std::shared_ptr<PthreadThread> result
+      = std::shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
                                                     toPthreadPriority(policy_, priority_),
                                                     stackSize_,
                                                     isDetached(),
diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h
index 5e04d01..cb3b17c 100644
--- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h
+++ b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h
@@ -22,7 +22,7 @@
 
 #include <thrift/concurrency/Thread.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -63,7 +63,7 @@
 
   /**
    * Posix thread (pthread) factory.  All threads created by a factory are reference-counted
-   * via stdcxx::shared_ptr.  The factory guarantees that threads and the Runnable tasks 
+   * via std::shared_ptr.  The factory guarantees that threads and the Runnable tasks 
    * they host will be properly cleaned up once the last strong reference to both is
    * given up.
    *
@@ -88,7 +88,7 @@
   PosixThreadFactory(bool detached);
 
   // From ThreadFactory;
-  stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
+  std::shared_ptr<Thread> newThread(std::shared_ptr<Runnable> runnable) const;
 
   // From ThreadFactory;
   Thread::id_t getCurrentThreadId() const;
diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp
index da0c5e3..c885f3a 100644
--- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp
+++ b/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp
@@ -24,7 +24,7 @@
 #include <thrift/concurrency/Exception.h>
 #include <thrift/concurrency/Monitor.h>
 #include <thrift/concurrency/StdThreadFactory.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <cassert>
 #include <thread>
@@ -42,11 +42,11 @@
  *
  * @version $Id:$
  */
-class StdThread : public Thread, public stdcxx::enable_shared_from_this<StdThread> {
+class StdThread : public Thread, public std::enable_shared_from_this<StdThread> {
 public:
   enum STATE { uninitialized, starting, started, stopping, stopped };
 
-  static void threadMain(stdcxx::shared_ptr<StdThread> thread);
+  static void threadMain(std::shared_ptr<StdThread> thread);
 
 private:
   std::unique_ptr<std::thread> thread_;
@@ -55,7 +55,7 @@
   bool detached_;
 
 public:
-  StdThread(bool detached, stdcxx::shared_ptr<Runnable> runnable)
+  StdThread(bool detached, std::shared_ptr<Runnable> runnable)
     : state_(uninitialized), detached_(detached) {
     this->Thread::runnable(runnable);
   }
@@ -93,7 +93,7 @@
       return;
     }
 
-    stdcxx::shared_ptr<StdThread> selfRef = shared_from_this();
+    std::shared_ptr<StdThread> selfRef = shared_from_this();
     setState(starting);
 
     Synchronized sync(monitor_);
@@ -116,12 +116,12 @@
 
   Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); }
 
-  stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
+  std::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
 
-  void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
+  void runnable(std::shared_ptr<Runnable> value) { Thread::runnable(value); }
 };
 
-void StdThread::threadMain(stdcxx::shared_ptr<StdThread> thread) {
+void StdThread::threadMain(std::shared_ptr<StdThread> thread) {
 #if GOOGLE_PERFTOOLS_REGISTER_THREAD
   ProfilerRegisterThread();
 #endif
@@ -137,8 +137,8 @@
 StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) {
 }
 
-stdcxx::shared_ptr<Thread> StdThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
-  stdcxx::shared_ptr<StdThread> result = stdcxx::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
+std::shared_ptr<Thread> StdThreadFactory::newThread(std::shared_ptr<Runnable> runnable) const {
+  std::shared_ptr<StdThread> result = std::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
   runnable->thread(result);
   return result;
 }
diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h b/lib/cpp/src/thrift/concurrency/StdThreadFactory.h
index 8e116b6..e74046b 100644
--- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h
+++ b/lib/cpp/src/thrift/concurrency/StdThreadFactory.h
@@ -22,7 +22,7 @@
 
 #include <thrift/concurrency/Thread.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -38,7 +38,7 @@
 public:
   /**
    * Std thread factory.  All threads created by a factory are reference-counted
-   * via stdcxx::shared_ptr.  The factory guarantees that threads and the Runnable tasks
+   * via std::shared_ptr.  The factory guarantees that threads and the Runnable tasks
    * they host will be properly cleaned up once the last strong reference
    * to both is given up.
    *
@@ -48,7 +48,7 @@
   StdThreadFactory(bool detached = true);
 
   // From ThreadFactory;
-  stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
+  std::shared_ptr<Thread> newThread(std::shared_ptr<Runnable> runnable) const;
 
   // From ThreadFactory;
   Thread::id_t getCurrentThreadId() const;
diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h
index 788623b..b2ea4e2 100644
--- a/lib/cpp/src/thrift/concurrency/Thread.h
+++ b/lib/cpp/src/thrift/concurrency/Thread.h
@@ -21,13 +21,11 @@
 #define _THRIFT_CONCURRENCY_THREAD_H_ 1
 
 #include <stdint.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <thrift/thrift-config.h>
 
-#if USE_BOOST_THREAD
-#include <boost/thread.hpp>
-#elif USE_STD_THREAD
+#if USE_STD_THREAD
 #include <thread>
 #else
 #ifdef HAVE_PTHREAD_H
@@ -56,16 +54,16 @@
    * Gets the thread object that is hosting this runnable object  - can return
    * an empty boost::shared pointer if no references remain on that thread object
    */
-  virtual stdcxx::shared_ptr<Thread> thread() { return thread_.lock(); }
+  virtual std::shared_ptr<Thread> thread() { return thread_.lock(); }
 
   /**
    * Sets the thread that is executing this object.  This is only meant for
    * use by concrete implementations of Thread.
    */
-  virtual void thread(stdcxx::shared_ptr<Thread> value) { thread_ = value; }
+  virtual void thread(std::shared_ptr<Thread> value) { thread_ = value; }
 
 private:
-  stdcxx::weak_ptr<Thread> thread_;
+  std::weak_ptr<Thread> thread_;
 };
 
 /**
@@ -80,12 +78,7 @@
 class Thread {
 
 public:
-#if USE_BOOST_THREAD
-  typedef boost::thread::id id_t;
-
-  static inline bool is_current(id_t t) { return t == boost::this_thread::get_id(); }
-  static inline id_t get_current() { return boost::this_thread::get_id(); }
-#elif USE_STD_THREAD
+#if USE_STD_THREAD
   typedef std::thread::id id_t;
 
   static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); }
@@ -121,13 +114,13 @@
   /**
    * Gets the runnable object this thread is hosting
    */
-  virtual stdcxx::shared_ptr<Runnable> runnable() const { return _runnable; }
+  virtual std::shared_ptr<Runnable> runnable() const { return _runnable; }
 
 protected:
-  virtual void runnable(stdcxx::shared_ptr<Runnable> value) { _runnable = value; }
+  virtual void runnable(std::shared_ptr<Runnable> value) { _runnable = value; }
 
 private:
-  stdcxx::shared_ptr<Runnable> _runnable;
+  std::shared_ptr<Runnable> _runnable;
 };
 
 /**
@@ -154,7 +147,7 @@
   /**
    * Create a new thread.
    */
-  virtual stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const = 0;
+  virtual std::shared_ptr<Thread> newThread(std::shared_ptr<Runnable> runnable) const = 0;
 
   /**
    * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread
diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
index 2e27b7f..58025f9 100644
--- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
+++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
@@ -24,7 +24,7 @@
 #include <thrift/concurrency/Monitor.h>
 #include <thrift/concurrency/Util.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <stdexcept>
 #include <deque>
@@ -34,8 +34,8 @@
 namespace thrift {
 namespace concurrency {
 
-using stdcxx::shared_ptr;
-using stdcxx::dynamic_pointer_cast;
+using std::shared_ptr;
+using std::dynamic_pointer_cast;
 
 /**
  * ThreadManager class
@@ -504,7 +504,7 @@
   }
 }
 
-stdcxx::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
+std::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
   Guard g(mutex_);
   if (state_ != ThreadManager::STARTED) {
     throw IllegalStateException(
@@ -513,7 +513,7 @@
   }
 
   if (tasks_.empty()) {
-    return stdcxx::shared_ptr<Runnable>();
+    return std::shared_ptr<Runnable>();
   }
 
   shared_ptr<ThreadManager::Task> task = tasks_.front();
diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h
index b3b7542..470fc0a 100644
--- a/lib/cpp/src/thrift/concurrency/ThreadManager.h
+++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h
@@ -20,9 +20,10 @@
 #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_
 #define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1
 
+#include <functional>
+#include <memory>
 #include <sys/types.h>
 #include <thrift/concurrency/Thread.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -58,7 +59,7 @@
   ThreadManager() {}
 
 public:
-  typedef apache::thrift::stdcxx::function<void(stdcxx::shared_ptr<Runnable>)> ExpireCallback;
+  typedef std::function<void(std::shared_ptr<Runnable>)> ExpireCallback;
 
   virtual ~ThreadManager() {}
 
@@ -87,14 +88,14 @@
   /**
    * \returns the current thread factory
    */
-  virtual stdcxx::shared_ptr<ThreadFactory> threadFactory() const = 0;
+  virtual std::shared_ptr<ThreadFactory> threadFactory() const = 0;
 
   /**
    * Set the thread factory.
    * \throws InvalidArgumentException if the new thread factory has a different
    *                                  detached disposition than the one replacing it
    */
-  virtual void threadFactory(stdcxx::shared_ptr<ThreadFactory> value) = 0;
+  virtual void threadFactory(std::shared_ptr<ThreadFactory> value) = 0;
 
   /**
    * Adds worker thread(s).
@@ -161,21 +162,21 @@
    *
    * @throws TooManyPendingTasksException Pending task count exceeds max pending task count
    */
-  virtual void add(stdcxx::shared_ptr<Runnable> task,
+  virtual void add(std::shared_ptr<Runnable> task,
                    int64_t timeout = 0LL,
                    int64_t expiration = 0LL) = 0;
 
   /**
    * Removes a pending task
    */
-  virtual void remove(stdcxx::shared_ptr<Runnable> task) = 0;
+  virtual void remove(std::shared_ptr<Runnable> task) = 0;
 
   /**
    * Remove the next pending task which would be run.
    *
    * @return the task removed.
    */
-  virtual stdcxx::shared_ptr<Runnable> removeNextPending() = 0;
+  virtual std::shared_ptr<Runnable> removeNextPending() = 0;
 
   /**
    * Remove tasks from front of task queue that have expired.
@@ -190,14 +191,14 @@
    */
   virtual void setExpireCallback(ExpireCallback expireCallback) = 0;
 
-  static stdcxx::shared_ptr<ThreadManager> newThreadManager();
+  static std::shared_ptr<ThreadManager> newThreadManager();
 
   /**
    * Creates a simple thread manager the uses count number of worker threads and has
    * a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit
    * on pending tasks
    */
-  static stdcxx::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
+  static std::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
                                                                  size_t pendingTaskCountMax = 0);
 
   class Task;
diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp
index 2017146..61a34ff 100644
--- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp
+++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp
@@ -29,8 +29,8 @@
 namespace thrift {
 namespace concurrency {
 
-using stdcxx::shared_ptr;
-using stdcxx::weak_ptr;
+using std::shared_ptr;
+using std::weak_ptr;
 
 /**
  * TimerManager class
diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h
index 2bfc6a7..ba79226 100644
--- a/lib/cpp/src/thrift/concurrency/TimerManager.h
+++ b/lib/cpp/src/thrift/concurrency/TimerManager.h
@@ -24,7 +24,7 @@
 #include <thrift/concurrency/Monitor.h>
 #include <thrift/concurrency/Thread.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <map>
 #include <time.h>
 
@@ -43,15 +43,15 @@
 
 public:
   class Task;
-  typedef stdcxx::weak_ptr<Task> Timer;
+  typedef std::weak_ptr<Task> Timer;
 
   TimerManager();
 
   virtual ~TimerManager();
 
-  virtual stdcxx::shared_ptr<const ThreadFactory> threadFactory() const;
+  virtual std::shared_ptr<const ThreadFactory> threadFactory() const;
 
-  virtual void threadFactory(stdcxx::shared_ptr<const ThreadFactory> value);
+  virtual void threadFactory(std::shared_ptr<const ThreadFactory> value);
 
   /**
    * Starts the timer manager service
@@ -74,7 +74,7 @@
    * @param timeout Time in milliseconds to delay before executing task
    * @return Handle of the timer, which can be used to remove the timer.
    */
-  virtual Timer add(stdcxx::shared_ptr<Runnable> task, int64_t timeout);
+  virtual Timer add(std::shared_ptr<Runnable> task, int64_t timeout);
 
   /**
    * Adds a task to be executed at some time in the future by a worker thread.
@@ -83,7 +83,7 @@
    * @param timeout Absolute time in the future to execute task.
    * @return Handle of the timer, which can be used to remove the timer.
    */
-  virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
+  virtual Timer add(std::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
 
   /**
    * Adds a task to be executed at some time in the future by a worker thread.
@@ -92,7 +92,7 @@
    * @param timeout Absolute time in the future to execute task.
    * @return Handle of the timer, which can be used to remove the timer.
    */
-  virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct timeval& timeout);
+  virtual Timer add(std::shared_ptr<Runnable> task, const struct timeval& timeout);
 
   /**
    * Removes a pending task
@@ -106,7 +106,7 @@
    * @throws UncancellableTaskException Specified task is already being
    *                                    executed or has completed execution.
    */
-  virtual void remove(stdcxx::shared_ptr<Runnable> task);
+  virtual void remove(std::shared_ptr<Runnable> task);
 
   /**
    * Removes a single pending task
@@ -127,17 +127,17 @@
   virtual STATE state() const;
 
 private:
-  stdcxx::shared_ptr<const ThreadFactory> threadFactory_;
+  std::shared_ptr<const ThreadFactory> threadFactory_;
   friend class Task;
-  std::multimap<int64_t, stdcxx::shared_ptr<Task> > taskMap_;
+  std::multimap<int64_t, std::shared_ptr<Task> > taskMap_;
   size_t taskCount_;
   Monitor monitor_;
   STATE state_;
   class Dispatcher;
   friend class Dispatcher;
-  stdcxx::shared_ptr<Dispatcher> dispatcher_;
-  stdcxx::shared_ptr<Thread> dispatcherThread_;
-  typedef std::multimap<int64_t, stdcxx::shared_ptr<TimerManager::Task> >::iterator task_iterator;
+  std::shared_ptr<Dispatcher> dispatcher_;
+  std::shared_ptr<Thread> dispatcherThread_;
+  typedef std::multimap<int64_t, std::shared_ptr<TimerManager::Task> >::iterator task_iterator;
   typedef std::pair<task_iterator, task_iterator> task_range;
 };
 }
diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.cpp b/lib/cpp/src/thrift/processor/PeekProcessor.cpp
index fa11a72..07f6ba5 100644
--- a/lib/cpp/src/thrift/processor/PeekProcessor.cpp
+++ b/lib/cpp/src/thrift/processor/PeekProcessor.cpp
@@ -34,26 +34,26 @@
 PeekProcessor::~PeekProcessor() {
 }
 
-void PeekProcessor::initialize(stdcxx::shared_ptr<TProcessor> actualProcessor,
-                               stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
-                               stdcxx::shared_ptr<TPipedTransportFactory> transportFactory) {
+void PeekProcessor::initialize(std::shared_ptr<TProcessor> actualProcessor,
+                               std::shared_ptr<TProtocolFactory> protocolFactory,
+                               std::shared_ptr<TPipedTransportFactory> transportFactory) {
   actualProcessor_ = actualProcessor;
   pipedProtocol_ = protocolFactory->getProtocol(targetTransport_);
   transportFactory_ = transportFactory;
   transportFactory_->initializeTargetTransport(targetTransport_);
 }
 
-stdcxx::shared_ptr<TTransport> PeekProcessor::getPipedTransport(stdcxx::shared_ptr<TTransport> in) {
+std::shared_ptr<TTransport> PeekProcessor::getPipedTransport(std::shared_ptr<TTransport> in) {
   return transportFactory_->getTransport(in);
 }
 
-void PeekProcessor::setTargetTransport(stdcxx::shared_ptr<TTransport> targetTransport) {
+void PeekProcessor::setTargetTransport(std::shared_ptr<TTransport> targetTransport) {
   targetTransport_ = targetTransport;
-  if (stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
-    memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
-  } else if (stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
-    memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(
-        stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
+  if (std::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
+    memoryBuffer_ = std::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
+  } else if (std::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
+    memoryBuffer_ = std::dynamic_pointer_cast<TMemoryBuffer>(
+        std::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
   }
 
   if (!memoryBuffer_) {
@@ -62,8 +62,8 @@
   }
 }
 
-bool PeekProcessor::process(stdcxx::shared_ptr<TProtocol> in,
-                            stdcxx::shared_ptr<TProtocol> out,
+bool PeekProcessor::process(std::shared_ptr<TProtocol> in,
+                            std::shared_ptr<TProtocol> out,
                             void* connectionContext) {
 
   std::string fname;
@@ -120,7 +120,7 @@
   (void)size;
 }
 
-void PeekProcessor::peek(stdcxx::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
+void PeekProcessor::peek(std::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
   (void)fid;
   in->skip(ftype);
 }
diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.h b/lib/cpp/src/thrift/processor/PeekProcessor.h
index f5c10da..efac2b9 100644
--- a/lib/cpp/src/thrift/processor/PeekProcessor.h
+++ b/lib/cpp/src/thrift/processor/PeekProcessor.h
@@ -25,7 +25,7 @@
 #include <thrift/transport/TTransport.h>
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TBufferTransports.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -47,34 +47,34 @@
   //             transportFactory - this TPipedTransportFactory is used to wrap the source transport
   //                                via a call to getPipedTransport
   void initialize(
-      stdcxx::shared_ptr<apache::thrift::TProcessor> actualProcessor,
-      stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
-      stdcxx::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory);
+      std::shared_ptr<apache::thrift::TProcessor> actualProcessor,
+      std::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
+      std::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory);
 
-  stdcxx::shared_ptr<apache::thrift::transport::TTransport> getPipedTransport(
-      stdcxx::shared_ptr<apache::thrift::transport::TTransport> in);
+  std::shared_ptr<apache::thrift::transport::TTransport> getPipedTransport(
+      std::shared_ptr<apache::thrift::transport::TTransport> in);
 
-  void setTargetTransport(stdcxx::shared_ptr<apache::thrift::transport::TTransport> targetTransport);
+  void setTargetTransport(std::shared_ptr<apache::thrift::transport::TTransport> targetTransport);
 
-  virtual bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> in,
-                       stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> out,
+  virtual bool process(std::shared_ptr<apache::thrift::protocol::TProtocol> in,
+                       std::shared_ptr<apache::thrift::protocol::TProtocol> out,
                        void* connectionContext);
 
   // The following three functions can be overloaded by child classes to
   // achieve desired peeking behavior
   virtual void peekName(const std::string& fname);
   virtual void peekBuffer(uint8_t* buffer, uint32_t size);
-  virtual void peek(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> in,
+  virtual void peek(std::shared_ptr<apache::thrift::protocol::TProtocol> in,
                     apache::thrift::protocol::TType ftype,
                     int16_t fid);
   virtual void peekEnd();
 
 private:
-  stdcxx::shared_ptr<apache::thrift::TProcessor> actualProcessor_;
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> pipedProtocol_;
-  stdcxx::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory_;
-  stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> memoryBuffer_;
-  stdcxx::shared_ptr<apache::thrift::transport::TTransport> targetTransport_;
+  std::shared_ptr<apache::thrift::TProcessor> actualProcessor_;
+  std::shared_ptr<apache::thrift::protocol::TProtocol> pipedProtocol_;
+  std::shared_ptr<apache::thrift::transport::TPipedTransportFactory> transportFactory_;
+  std::shared_ptr<apache::thrift::transport::TMemoryBuffer> memoryBuffer_;
+  std::shared_ptr<apache::thrift::transport::TTransport> targetTransport_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/processor/StatsProcessor.h b/lib/cpp/src/thrift/processor/StatsProcessor.h
index 8f6725f..e98efb8 100644
--- a/lib/cpp/src/thrift/processor/StatsProcessor.h
+++ b/lib/cpp/src/thrift/processor/StatsProcessor.h
@@ -20,7 +20,7 @@
 #ifndef STATSPROCESSOR_H
 #define STATSPROCESSOR_H
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TTransport.h>
 #include <thrift/protocol/TProtocol.h>
 #include <TProcessor.h>
@@ -38,8 +38,8 @@
   StatsProcessor(bool print, bool frequency) : print_(print), frequency_(frequency) {}
   virtual ~StatsProcessor(){};
 
-  virtual bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> piprot,
-                       stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> poprot,
+  virtual bool process(std::shared_ptr<apache::thrift::protocol::TProtocol> piprot,
+                       std::shared_ptr<apache::thrift::protocol::TProtocol> poprot,
                        void* serverContext) {
 
     piprot_ = piprot;
@@ -229,7 +229,7 @@
     }
   }
 
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> piprot_;
+  std::shared_ptr<apache::thrift::protocol::TProtocol> piprot_;
   std::map<std::string, int64_t> frequency_map_;
 
   bool print_;
diff --git a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
index aa3d49f..2aa7f75 100644
--- a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
+++ b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
@@ -36,7 +36,7 @@
  */
 class StoredMessageProtocol : public TProtocolDecorator {
 public:
-  StoredMessageProtocol(stdcxx::shared_ptr<protocol::TProtocol> _protocol,
+  StoredMessageProtocol(std::shared_ptr<protocol::TProtocol> _protocol,
                         const std::string& _name,
                         const TMessageType _type,
                         const int32_t _seqid)
@@ -65,19 +65,19 @@
  * processors with it, as shown in the following example:</p>
  *
  * <blockquote><code>
- *     stdcxx::shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
+ *     std::shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
  *
  *     processor->registerProcessor(
  *         "Calculator",
- *         stdcxx::shared_ptr<TProcessor>( new CalculatorProcessor(
- *             stdcxx::shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
+ *         std::shared_ptr<TProcessor>( new CalculatorProcessor(
+ *             std::shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
  *
  *     processor->registerProcessor(
  *         "WeatherReport",
- *         stdcxx::shared_ptr<TProcessor>( new WeatherReportProcessor(
- *             stdcxx::shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
+ *         std::shared_ptr<TProcessor>( new WeatherReportProcessor(
+ *             std::shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
  *
- *     stdcxx::shared_ptr<TServerTransport> transport(new TServerSocket(9090));
+ *     std::shared_ptr<TServerTransport> transport(new TServerSocket(9090));
  *     TSimpleServer server(processor, transport);
  *
  *     server.serve();
@@ -85,7 +85,7 @@
  */
 class TMultiplexedProcessor : public TProcessor {
 public:
-  typedef std::map<std::string, stdcxx::shared_ptr<TProcessor> > services_t;
+  typedef std::map<std::string, std::shared_ptr<TProcessor> > services_t;
 
   /**
     * 'Register' a service with this <code>TMultiplexedProcessor</code>.  This
@@ -98,7 +98,7 @@
     *                         as "handlers", e.g. WeatherReportHandler,
     *                         implementing WeatherReportIf interface.
     */
-  void registerProcessor(const std::string& serviceName, stdcxx::shared_ptr<TProcessor> processor) {
+  void registerProcessor(const std::string& serviceName, std::shared_ptr<TProcessor> processor) {
     services[serviceName] = processor;
   }
 
@@ -106,15 +106,15 @@
    * Register a service to be called to process queries without service name
    * \param [in] processor   Implementation of a service.
    */
-  void registerDefault(const stdcxx::shared_ptr<TProcessor>& processor) {
+  void registerDefault(const std::shared_ptr<TProcessor>& processor) {
     defaultProcessor = processor;
   }
 
   /**
    * Chew up invalid input and return an exception to throw.
    */
-  TException protocol_error(stdcxx::shared_ptr<protocol::TProtocol> in,
-                            stdcxx::shared_ptr<protocol::TProtocol> out,
+  TException protocol_error(std::shared_ptr<protocol::TProtocol> in,
+                            std::shared_ptr<protocol::TProtocol> out,
                             const std::string& name, 
                             int32_t seqid, 
                             const std::string& msg) const {
@@ -147,8 +147,8 @@
    * the service name was not found in the message, or if the service
    * name was not found in the service map.
    */
-  bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
-               stdcxx::shared_ptr<protocol::TProtocol> out,
+  bool process(std::shared_ptr<protocol::TProtocol> in,
+               std::shared_ptr<protocol::TProtocol> out,
                void* connectionContext) {
     std::string name;
     protocol::TMessageType type;
@@ -177,11 +177,11 @@
       services_t::iterator it = services.find(tokens[0]);
 
       if (it != services.end()) {
-        stdcxx::shared_ptr<TProcessor> processor = it->second;
+        std::shared_ptr<TProcessor> processor = it->second;
         // Let the processor registered for this service name
         // process the message.
         return processor
-            ->process(stdcxx::shared_ptr<protocol::TProtocol>(
+            ->process(std::shared_ptr<protocol::TProtocol>(
                           new protocol::StoredMessageProtocol(in, tokens[1], type, seqid)),
                       out,
                       connectionContext);
@@ -195,7 +195,7 @@
 	  if (defaultProcessor) {
         // non-multiplexed client forwards to default processor
         return defaultProcessor            
-            ->process(stdcxx::shared_ptr<protocol::TProtocol>(
+            ->process(std::shared_ptr<protocol::TProtocol>(
                           new protocol::StoredMessageProtocol(in, tokens[0], type, seqid)),
                       out,
                       connectionContext);
@@ -216,7 +216,7 @@
   
   //! If a non-multi client requests something, it goes to the
   //! default processor (if one is defined) for backwards compatibility.
-  stdcxx::shared_ptr<TProcessor> defaultProcessor;
+  std::shared_ptr<TProcessor> defaultProcessor;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp
index beb76eb..7474f5a 100644
--- a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp
+++ b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp
@@ -19,8 +19,6 @@
 
 #include <thrift/protocol/TBase64Utils.h>
 
-#include <boost/static_assert.hpp>
-
 using std::string;
 
 namespace apache {
diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
index f28d278..9067758 100644
--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
@@ -23,7 +23,7 @@
 #include <thrift/protocol/TProtocol.h>
 #include <thrift/protocol/TVirtualProtocol.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -41,7 +41,7 @@
   static const int32_t VERSION_1 = ((int32_t)0x80010000);
   // VERSION_2 (0x80020000) was taken by TDenseProtocol (which has since been removed)
 
-  TBinaryProtocolT(stdcxx::shared_ptr<Transport_> trans)
+  TBinaryProtocolT(std::shared_ptr<Transport_> trans)
     : TVirtualProtocol<TBinaryProtocolT<Transport_, ByteOrder_> >(trans),
       trans_(trans.get()),
       string_limit_(0),
@@ -49,7 +49,7 @@
       strict_read_(false),
       strict_write_(true) {}
 
-  TBinaryProtocolT(stdcxx::shared_ptr<Transport_> trans,
+  TBinaryProtocolT(std::shared_ptr<Transport_> trans,
                    int32_t string_limit,
                    int32_t container_limit,
                    bool strict_read,
@@ -212,8 +212,8 @@
     strict_write_ = strict_write;
   }
 
-  stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
-    stdcxx::shared_ptr<Transport_> specific_trans = stdcxx::dynamic_pointer_cast<Transport_>(trans);
+  std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) {
+    std::shared_ptr<Transport_> specific_trans = std::dynamic_pointer_cast<Transport_>(trans);
     TProtocol* prot;
     if (specific_trans) {
       prot = new TBinaryProtocolT<Transport_, ByteOrder_>(specific_trans,
@@ -229,7 +229,7 @@
                                                           strict_write_);
     }
 
-    return stdcxx::shared_ptr<TProtocol>(prot);
+    return std::shared_ptr<TProtocol>(prot);
   }
 
 private:
diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
index d6f6dbb..fe73992 100644
--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
+++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc
@@ -165,8 +165,8 @@
 
 template <class Transport_, class ByteOrder_>
 uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeDouble(const double dub) {
-  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
-  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
+  static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)");
+  static_assert(std::numeric_limits<double>::is_iec559, "std::numeric_limits<double>::is_iec559");
 
   uint64_t bits = bitwise_cast<uint64_t>(dub);
   bits = ByteOrder_::toWire64(bits);
@@ -388,8 +388,8 @@
 
 template <class Transport_, class ByteOrder_>
 uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::readDouble(double& dub) {
-  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
-  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
+  static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)");
+  static_assert(std::numeric_limits<double>::is_iec559, "std::numeric_limits<double>::is_iec559");
 
   union bytes {
     uint8_t b[8];
diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.h b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
index e6024a9..5cfb47d 100644
--- a/lib/cpp/src/thrift/protocol/TCompactProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
@@ -23,7 +23,7 @@
 #include <thrift/protocol/TVirtualProtocol.h>
 
 #include <stack>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -74,7 +74,7 @@
   int16_t lastFieldId_;
 
 public:
-  TCompactProtocolT(stdcxx::shared_ptr<Transport_> trans)
+  TCompactProtocolT(std::shared_ptr<Transport_> trans)
     : TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
       trans_(trans.get()),
       lastFieldId_(0),
@@ -86,7 +86,7 @@
     boolValue_.hasBoolValue = false;
   }
 
-  TCompactProtocolT(stdcxx::shared_ptr<Transport_> trans,
+  TCompactProtocolT(std::shared_ptr<Transport_> trans,
                     int32_t string_limit,
                     int32_t container_limit)
     : TVirtualProtocol<TCompactProtocolT<Transport_> >(trans),
@@ -239,8 +239,8 @@
 
   void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; }
 
-  stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
-    stdcxx::shared_ptr<Transport_> specific_trans = stdcxx::dynamic_pointer_cast<Transport_>(trans);
+  std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) {
+    std::shared_ptr<Transport_> specific_trans = std::dynamic_pointer_cast<Transport_>(trans);
     TProtocol* prot;
     if (specific_trans) {
       prot = new TCompactProtocolT<Transport_>(specific_trans, string_limit_, container_limit_);
@@ -248,7 +248,7 @@
       prot = new TCompactProtocol(trans, string_limit_, container_limit_);
     }
 
-    return stdcxx::shared_ptr<TProtocol>(prot);
+    return std::shared_ptr<TProtocol>(prot);
   }
 
 private:
diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc
index d40c331..8efec6e 100644
--- a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc
+++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc
@@ -253,8 +253,8 @@
  */
 template <class Transport_>
 uint32_t TCompactProtocolT<Transport_>::writeDouble(const double dub) {
-  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
-  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
+  static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)");
+  static_assert(std::numeric_limits<double>::is_iec559, "std::numeric_limits<double>::is_iec559");
 
   uint64_t bits = bitwise_cast<uint64_t>(dub);
   bits = THRIFT_htolell(bits);
@@ -653,8 +653,8 @@
  */
 template <class Transport_>
 uint32_t TCompactProtocolT<Transport_>::readDouble(double& dub) {
-  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
-  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
+  static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)");
+  static_assert(std::numeric_limits<double>::is_iec559, "std::numeric_limits<double>::is_iec559");
 
   union {
     uint64_t bits;
diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp
index d3c6beb..0e6d4a2 100644
--- a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp
+++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp
@@ -24,7 +24,6 @@
 #include <cctype>
 #include <cstdio>
 #include <stdexcept>
-#include <boost/static_assert.hpp>
 
 using std::string;
 
diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.h b/lib/cpp/src/thrift/protocol/TDebugProtocol.h
index 301d05a..c079624 100644
--- a/lib/cpp/src/thrift/protocol/TDebugProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.h
@@ -22,7 +22,7 @@
 
 #include <thrift/protocol/TVirtualProtocol.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -51,7 +51,7 @@
   enum write_state_t { UNINIT, STRUCT, LIST, SET, MAP_KEY, MAP_VALUE };
 
 public:
-  TDebugProtocol(stdcxx::shared_ptr<TTransport> trans)
+  TDebugProtocol(std::shared_ptr<TTransport> trans)
     : TVirtualProtocol<TDebugProtocol>(trans),
       trans_(trans.get()),
       string_limit_(DEFAULT_STRING_LIMIT),
@@ -141,8 +141,8 @@
   TDebugProtocolFactory() {}
   virtual ~TDebugProtocolFactory() {}
 
-  stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TProtocol>(new TDebugProtocol(trans));
+  std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TProtocol>(new TDebugProtocol(trans));
   }
 };
 }
@@ -160,7 +160,7 @@
   using namespace apache::thrift::transport;
   using namespace apache::thrift::protocol;
   TMemoryBuffer* buffer = new TMemoryBuffer;
-  stdcxx::shared_ptr<TTransport> trans(buffer);
+  std::shared_ptr<TTransport> trans(buffer);
   TDebugProtocol protocol(trans);
 
   ts.write(&protocol);
@@ -178,7 +178,7 @@
   using namespace apache::thrift::transport;
   using namespace apache::thrift::protocol;
   TMemoryBuffer* buffer = new TMemoryBuffer;
-  stdcxx::shared_ptr<TTransport> trans(buffer);
+  std::shared_ptr<TTransport> trans(buffer);
   TDebugProtocol protocol(trans);
 
   // I am gross!
diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp
index 2667617..6242e30 100644
--- a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp
+++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp
@@ -26,8 +26,7 @@
 
 #include <limits>
 
-#include <boost/static_assert.hpp>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -42,11 +41,11 @@
 
   switch (protoId_) {
   case T_BINARY_PROTOCOL:
-    proto_ = stdcxx::make_shared<TBinaryProtocolT<THeaderTransport> >(trans_);
+    proto_ = std::make_shared<TBinaryProtocolT<THeaderTransport> >(trans_);
     break;
 
   case T_COMPACT_PROTOCOL:
-    proto_ = stdcxx::make_shared<TCompactProtocolT<THeaderTransport> >(trans_);
+    proto_ = std::make_shared<TCompactProtocolT<THeaderTransport> >(trans_);
     break;
 
   default:
diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.h b/lib/cpp/src/thrift/protocol/THeaderProtocol.h
index 8cd5017..e5e2b65 100644
--- a/lib/cpp/src/thrift/protocol/THeaderProtocol.h
+++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.h
@@ -25,7 +25,7 @@
 #include <thrift/protocol/TVirtualProtocol.h>
 #include <thrift/transport/THeaderTransport.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 using apache::thrift::transport::THeaderTransport;
 
@@ -43,21 +43,21 @@
 public:
   void resetProtocol();
 
-  explicit THeaderProtocol(const stdcxx::shared_ptr<TTransport>& trans,
+  explicit THeaderProtocol(const std::shared_ptr<TTransport>& trans,
                            uint16_t protoId = T_COMPACT_PROTOCOL)
-    : TVirtualProtocol<THeaderProtocol>(stdcxx::shared_ptr<TTransport>(new THeaderTransport(trans))),
-      trans_(stdcxx::dynamic_pointer_cast<THeaderTransport>(getTransport())),
+    : TVirtualProtocol<THeaderProtocol>(std::shared_ptr<TTransport>(new THeaderTransport(trans))),
+      trans_(std::dynamic_pointer_cast<THeaderTransport>(getTransport())),
       protoId_(protoId) {
     trans_->setProtocolId(protoId);
     resetProtocol();
   }
 
-  THeaderProtocol(const stdcxx::shared_ptr<TTransport>& inTrans,
-                  const stdcxx::shared_ptr<TTransport>& outTrans,
+  THeaderProtocol(const std::shared_ptr<TTransport>& inTrans,
+                  const std::shared_ptr<TTransport>& outTrans,
                   uint16_t protoId = T_COMPACT_PROTOCOL)
     : TVirtualProtocol<THeaderProtocol>(
-          stdcxx::shared_ptr<TTransport>(new THeaderTransport(inTrans, outTrans))),
-      trans_(stdcxx::dynamic_pointer_cast<THeaderTransport>(getTransport())),
+          std::shared_ptr<TTransport>(new THeaderTransport(inTrans, outTrans))),
+      trans_(std::dynamic_pointer_cast<THeaderTransport>(getTransport())),
       protoId_(protoId) {
     trans_->setProtocolId(protoId);
     resetProtocol();
@@ -182,25 +182,25 @@
   uint32_t readBinary(std::string& binary);
 
 protected:
-  stdcxx::shared_ptr<THeaderTransport> trans_;
+  std::shared_ptr<THeaderTransport> trans_;
 
-  stdcxx::shared_ptr<TProtocol> proto_;
+  std::shared_ptr<TProtocol> proto_;
   uint32_t protoId_;
 };
 
 class THeaderProtocolFactory : public TProtocolFactory {
 public:
-  virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<transport::TTransport> trans) {
+  virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<transport::TTransport> trans) {
     THeaderProtocol* headerProtocol
         = new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL);
-    return stdcxx::shared_ptr<TProtocol>(headerProtocol);
+    return std::shared_ptr<TProtocol>(headerProtocol);
   }
 
-  virtual stdcxx::shared_ptr<TProtocol> getProtocol(
-      stdcxx::shared_ptr<transport::TTransport> inTrans,
-      stdcxx::shared_ptr<transport::TTransport> outTrans) {
+  virtual std::shared_ptr<TProtocol> getProtocol(
+      std::shared_ptr<transport::TTransport> inTrans,
+      std::shared_ptr<transport::TTransport> outTrans) {
     THeaderProtocol* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL);
-    return stdcxx::shared_ptr<TProtocol>(headerProtocol);
+    return std::shared_ptr<TProtocol>(headerProtocol);
   }
 };
 }
diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
index a49a148..4576fa1 100644
--- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
+++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
@@ -49,7 +49,6 @@
 static const uint8_t kJSONElemSeparator = ',';
 static const uint8_t kJSONBackslash = '\\';
 static const uint8_t kJSONStringDelimiter = '"';
-static const uint8_t kJSONZeroChar = '0';
 static const uint8_t kJSONEscapeChar = 'u';
 
 static const std::string kJSONEscapePrefix("\\u00");
@@ -398,7 +397,7 @@
   bool first_;
 };
 
-TJSONProtocol::TJSONProtocol(stdcxx::shared_ptr<TTransport> ptrans)
+TJSONProtocol::TJSONProtocol(std::shared_ptr<TTransport> ptrans)
   : TVirtualProtocol<TJSONProtocol>(ptrans),
     trans_(ptrans.get()),
     context_(new TJSONContext()),
@@ -408,7 +407,7 @@
 TJSONProtocol::~TJSONProtocol() {
 }
 
-void TJSONProtocol::pushContext(stdcxx::shared_ptr<TJSONContext> c) {
+void TJSONProtocol::pushContext(std::shared_ptr<TJSONContext> c) {
   contexts_.push(context_);
   context_ = c;
 }
@@ -576,7 +575,7 @@
 uint32_t TJSONProtocol::writeJSONObjectStart() {
   uint32_t result = context_->write(*trans_);
   trans_->write(&kJSONObjectStart, 1);
-  pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONPairContext()));
+  pushContext(std::shared_ptr<TJSONContext>(new JSONPairContext()));
   return result + 1;
 }
 
@@ -589,7 +588,7 @@
 uint32_t TJSONProtocol::writeJSONArrayStart() {
   uint32_t result = context_->write(*trans_);
   trans_->write(&kJSONArrayStart, 1);
-  pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONListContext()));
+  pushContext(std::shared_ptr<TJSONContext>(new JSONListContext()));
   return result + 1;
 }
 
@@ -899,7 +898,7 @@
       }
       try {
         num = fromString<double>(str);
-      } catch (std::runtime_error e) {
+      } catch (std::runtime_error& e) {
         throw TProtocolException(TProtocolException::INVALID_DATA,
                                      "Expected numeric value; got \"" + str + "\"");
       }
@@ -912,7 +911,7 @@
     result += readJSONNumericChars(str);
     try {
       num = fromString<double>(str);
-    } catch (std::runtime_error e) {
+    } catch (std::runtime_error& e) {
       throw TProtocolException(TProtocolException::INVALID_DATA,
                                    "Expected numeric value; got \"" + str + "\"");
     }
@@ -923,7 +922,7 @@
 uint32_t TJSONProtocol::readJSONObjectStart() {
   uint32_t result = context_->read(reader_);
   result += readJSONSyntaxChar(kJSONObjectStart);
-  pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONPairContext()));
+  pushContext(std::shared_ptr<TJSONContext>(new JSONPairContext()));
   return result;
 }
 
@@ -936,7 +935,7 @@
 uint32_t TJSONProtocol::readJSONArrayStart() {
   uint32_t result = context_->read(reader_);
   result += readJSONSyntaxChar(kJSONArrayStart);
-  pushContext(stdcxx::shared_ptr<TJSONContext>(new JSONListContext()));
+  pushContext(std::shared_ptr<TJSONContext>(new JSONListContext()));
   return result;
 }
 
diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
index 16dff56..9c2f872 100644
--- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
@@ -96,12 +96,12 @@
  */
 class TJSONProtocol : public TVirtualProtocol<TJSONProtocol> {
 public:
-  TJSONProtocol(stdcxx::shared_ptr<TTransport> ptrans);
+  TJSONProtocol(std::shared_ptr<TTransport> ptrans);
 
   ~TJSONProtocol();
 
 private:
-  void pushContext(stdcxx::shared_ptr<TJSONContext> c);
+  void pushContext(std::shared_ptr<TJSONContext> c);
 
   void popContext();
 
@@ -276,8 +276,8 @@
 private:
   TTransport* trans_;
 
-  std::stack<stdcxx::shared_ptr<TJSONContext> > contexts_;
-  stdcxx::shared_ptr<TJSONContext> context_;
+  std::stack<std::shared_ptr<TJSONContext> > contexts_;
+  std::shared_ptr<TJSONContext> context_;
   LookaheadReader reader_;
 };
 
@@ -290,8 +290,8 @@
 
   virtual ~TJSONProtocolFactory() {}
 
-  stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TProtocol>(new TJSONProtocol(trans));
+  std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TProtocol>(new TJSONProtocol(trans));
   }
 };
 }
@@ -309,7 +309,7 @@
   using namespace apache::thrift::transport;
   using namespace apache::thrift::protocol;
   TMemoryBuffer* buffer = new TMemoryBuffer;
-  stdcxx::shared_ptr<TTransport> trans(buffer);
+  std::shared_ptr<TTransport> trans(buffer);
   TJSONProtocol protocol(trans);
 
   ts.write(&protocol);
diff --git a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h
index dd7e88f..94bd82e 100644
--- a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h
@@ -25,7 +25,7 @@
 namespace apache {
 namespace thrift {
 namespace protocol {
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 /**
  * <code>TMultiplexedProtocol</code> is a protocol-independent concrete decorator
diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h
index aa5beea..bbc6816 100644
--- a/lib/cpp/src/thrift/protocol/TProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TProtocol.h
@@ -28,8 +28,7 @@
 #include <thrift/transport/TTransport.h>
 #include <thrift/protocol/TProtocolException.h>
 
-#include <thrift/stdcxx.h>
-#include <boost/static_assert.hpp>
+#include <memory>
 
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
@@ -48,7 +47,7 @@
 // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
 template <typename To, typename From>
 static inline To bitwise_cast(From from) {
-  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
+  static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)");
 
   // BAD!!!  These are all broken with -O2.
   //return *reinterpret_cast<To*>(&from);  // BAD!!!
@@ -550,12 +549,12 @@
   }
   virtual uint32_t skip_virt(TType type);
 
-  inline stdcxx::shared_ptr<TTransport> getTransport() { return ptrans_; }
+  inline std::shared_ptr<TTransport> getTransport() { return ptrans_; }
 
   // TODO: remove these two calls, they are for backwards
   // compatibility
-  inline stdcxx::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
-  inline stdcxx::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
+  inline std::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
+  inline std::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
 
   // input and output recursion depth are kept separate so that one protocol
   // can be used concurrently for both input and output.
@@ -577,11 +576,11 @@
   void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
 
 protected:
-  TProtocol(stdcxx::shared_ptr<TTransport> ptrans)
+  TProtocol(std::shared_ptr<TTransport> ptrans)
     : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(DEFAULT_RECURSION_LIMIT)
   {}
 
-  stdcxx::shared_ptr<TTransport> ptrans_;
+  std::shared_ptr<TTransport> ptrans_;
 
 private:
   TProtocol() {}
@@ -599,9 +598,9 @@
 
   virtual ~TProtocolFactory();
 
-  virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> trans) = 0;
-  virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<TTransport> inTrans,
-               stdcxx::shared_ptr<TTransport> outTrans) {
+  virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) = 0;
+  virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> inTrans,
+               std::shared_ptr<TTransport> outTrans) {
     (void)outTrans;
     return getProtocol(inTrans);
   }
diff --git a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h
index a353b79..743a0f4 100644
--- a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h
+++ b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h
@@ -21,12 +21,12 @@
 #define THRIFT_TPROTOCOLDECORATOR_H_ 1
 
 #include <thrift/protocol/TProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
 namespace protocol {
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 /**
  * <code>TProtocolDecorator</code> forwards all requests to an enclosed
diff --git a/lib/cpp/src/thrift/protocol/TProtocolException.h b/lib/cpp/src/thrift/protocol/TProtocolException.h
index 6e536b4..10178e1 100644
--- a/lib/cpp/src/thrift/protocol/TProtocolException.h
+++ b/lib/cpp/src/thrift/protocol/TProtocolException.h
@@ -59,7 +59,7 @@
   TProtocolException(TProtocolExceptionType type, const std::string& message)
     : apache::thrift::TException(message), type_(type) {}
 
-  virtual ~TProtocolException() throw() {}
+  virtual ~TProtocolException() noexcept {}
 
   /**
    * Returns an error code that provides information about the type of error
@@ -69,7 +69,7 @@
    */
   TProtocolExceptionType getType() const { return type_; }
 
-  virtual const char* what() const throw() {
+  virtual const char* what() const noexcept {
     if (message_.empty()) {
       switch (type_) {
       case UNKNOWN:
diff --git a/lib/cpp/src/thrift/protocol/TProtocolTap.h b/lib/cpp/src/thrift/protocol/TProtocolTap.h
index 176d4fd..d000ba6 100644
--- a/lib/cpp/src/thrift/protocol/TProtocolTap.h
+++ b/lib/cpp/src/thrift/protocol/TProtocolTap.h
@@ -36,7 +36,7 @@
  */
 class TProtocolTap : public TVirtualProtocol<TProtocolTap> {
 public:
-  TProtocolTap(stdcxx::shared_ptr<TProtocol> source, stdcxx::shared_ptr<TProtocol> sink)
+  TProtocolTap(std::shared_ptr<TProtocol> source, std::shared_ptr<TProtocol> sink)
     : TVirtualProtocol<TProtocolTap>(source->getTransport()), source_(source), sink_(sink) {}
 
   uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
@@ -167,8 +167,8 @@
   }
 
 private:
-  stdcxx::shared_ptr<TProtocol> source_;
-  stdcxx::shared_ptr<TProtocol> sink_;
+  std::shared_ptr<TProtocol> source_;
+  std::shared_ptr<TProtocol> sink_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h
index 628b494..4eea579 100644
--- a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h
+++ b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h
@@ -301,7 +301,7 @@
   uint32_t skip(TType type) { return ::apache::thrift::protocol::skip(*this, type); }
 
 protected:
-  TProtocolDefaults(stdcxx::shared_ptr<TTransport> ptrans) : TProtocol(ptrans) {}
+  TProtocolDefaults(std::shared_ptr<TTransport> ptrans) : TProtocol(ptrans) {}
 };
 
 /**
@@ -504,7 +504,7 @@
   using Super_::readBool; // so we don't hide readBool(bool&)
 
 protected:
-  TVirtualProtocol(stdcxx::shared_ptr<TTransport> ptrans) : Super_(ptrans) {}
+  TVirtualProtocol(std::shared_ptr<TTransport> ptrans) : Super_(ptrans) {}
 };
 }
 }
diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp
index cd38b01..f77c993 100644
--- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp
+++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp
@@ -23,12 +23,12 @@
 #include <QIODevice>
 
 #include <thrift/transport/TBufferTransports.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 namespace transport {
 
@@ -91,7 +91,7 @@
                               "read(): underlying QIODevice is not open");
   }
 
-  actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable());
+  actualSize = (uint32_t)(std::min)((qint64)len, dev_->bytesAvailable());
   readSize = dev_->read(reinterpret_cast<char*>(buf), actualSize);
 
   if (readSize < 0) {
diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h
index 9087f2c..91ce8d5 100644
--- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h
+++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_
 #define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <thrift/transport/TVirtualTransport.h>
 
@@ -36,7 +36,7 @@
 class TQIODeviceTransport
     : public apache::thrift::transport::TVirtualTransport<TQIODeviceTransport> {
 public:
-  explicit TQIODeviceTransport(stdcxx::shared_ptr<QIODevice> dev);
+  explicit TQIODeviceTransport(std::shared_ptr<QIODevice> dev);
   virtual ~TQIODeviceTransport();
 
   void open();
@@ -59,7 +59,7 @@
   TQIODeviceTransport(const TQIODeviceTransport&);
   TQIODeviceTransport& operator=(const TQIODeviceTransport&);
 
-  stdcxx::shared_ptr<QIODevice> dev_;
+  std::shared_ptr<QIODevice> dev_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.cpp b/lib/cpp/src/thrift/qt/TQTcpServer.cpp
index c4669d7..99aad07 100644
--- a/lib/cpp/src/thrift/qt/TQTcpServer.cpp
+++ b/lib/cpp/src/thrift/qt/TQTcpServer.cpp
@@ -17,14 +17,15 @@
  * under the License.
  */
 
+#include <functional>
+#include <memory>
+
 #include <thrift/qt/TQTcpServer.h>
 #include <thrift/qt/TQIODeviceTransport.h>
 
 #include <QMetaType>
 #include <QTcpSocket>
 
-#include <thrift/stdcxx.h>
-
 #include <thrift/protocol/TProtocol.h>
 #include <thrift/async/TAsyncProcessor.h>
 
@@ -33,10 +34,10 @@
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
 using apache::thrift::transport::TQIODeviceTransport;
-using apache::thrift::stdcxx::bind;
-using apache::thrift::stdcxx::function;
-using apache::thrift::stdcxx::placeholders::_1;
-using apache::thrift::stdcxx::shared_ptr;
+using std::bind;
+using std::function;
+using std::placeholders::_1;
+using std::shared_ptr;
 
 QT_USE_NAMESPACE
 
diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.h b/lib/cpp/src/thrift/qt/TQTcpServer.h
index 0d32afa..8e3fe3a 100644
--- a/lib/cpp/src/thrift/qt/TQTcpServer.h
+++ b/lib/cpp/src/thrift/qt/TQTcpServer.h
@@ -23,7 +23,7 @@
 #include <QObject>
 #include <QTcpServer>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -47,9 +47,9 @@
 class TQTcpServer : public QObject {
   Q_OBJECT
 public:
-  TQTcpServer(stdcxx::shared_ptr<QTcpServer> server,
-              stdcxx::shared_ptr<TAsyncProcessor> processor,
-              stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
+  TQTcpServer(std::shared_ptr<QTcpServer> server,
+              std::shared_ptr<TAsyncProcessor> processor,
+              std::shared_ptr<apache::thrift::protocol::TProtocolFactory> protocolFactory,
               QObject* parent = NULL);
   virtual ~TQTcpServer();
 
@@ -65,13 +65,13 @@
   struct ConnectionContext;
 
   void scheduleDeleteConnectionContext(QTcpSocket* connection);
-  void finish(stdcxx::shared_ptr<ConnectionContext> ctx, bool healthy);
+  void finish(std::shared_ptr<ConnectionContext> ctx, bool healthy);
 
-  stdcxx::shared_ptr<QTcpServer> server_;
-  stdcxx::shared_ptr<TAsyncProcessor> processor_;
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
+  std::shared_ptr<QTcpServer> server_;
+  std::shared_ptr<TAsyncProcessor> processor_;
+  std::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
 
-  typedef std::map<QTcpSocket*, stdcxx::shared_ptr<ConnectionContext> > ConnectionContextMap;
+  typedef std::map<QTcpSocket*, std::shared_ptr<ConnectionContext> > ConnectionContextMap;
   ConnectionContextMap ctxMap_;
 };
 }
diff --git a/lib/cpp/src/thrift/server/TConnectedClient.cpp b/lib/cpp/src/thrift/server/TConnectedClient.cpp
index 33ec3a9..acdaa77 100644
--- a/lib/cpp/src/thrift/server/TConnectedClient.cpp
+++ b/lib/cpp/src/thrift/server/TConnectedClient.cpp
@@ -28,7 +28,7 @@
 using apache::thrift::server::TServerEventHandler;
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::string;
 
 TConnectedClient::TConnectedClient(const shared_ptr<TProcessor>& processor,
diff --git a/lib/cpp/src/thrift/server/TConnectedClient.h b/lib/cpp/src/thrift/server/TConnectedClient.h
index 2f9d4c9..19e70c1 100644
--- a/lib/cpp/src/thrift/server/TConnectedClient.h
+++ b/lib/cpp/src/thrift/server/TConnectedClient.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_
 #define _THRIFT_SERVER_TCONNECTEDCLIENT_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/TProcessor.h>
 #include <thrift/protocol/TProtocol.h>
 #include <thrift/server/TServer.h>
@@ -49,11 +49,11 @@
    * @param[in] client         the TTransport representing the client
    */
   TConnectedClient(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocol>& inputProtocol,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocol>& outputProtocol,
-      const stdcxx::shared_ptr<apache::thrift::server::TServerEventHandler>& eventHandler,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransport>& client);
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::protocol::TProtocol>& inputProtocol,
+      const std::shared_ptr<apache::thrift::protocol::TProtocol>& outputProtocol,
+      const std::shared_ptr<apache::thrift::server::TServerEventHandler>& eventHandler,
+      const std::shared_ptr<apache::thrift::transport::TTransport>& client);
 
   /**
    * Destructor.
@@ -92,11 +92,11 @@
   virtual void cleanup();
 
 private:
-  stdcxx::shared_ptr<apache::thrift::TProcessor> processor_;
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> inputProtocol_;
-  stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> outputProtocol_;
-  stdcxx::shared_ptr<apache::thrift::server::TServerEventHandler> eventHandler_;
-  stdcxx::shared_ptr<apache::thrift::transport::TTransport> client_;
+  std::shared_ptr<apache::thrift::TProcessor> processor_;
+  std::shared_ptr<apache::thrift::protocol::TProtocol> inputProtocol_;
+  std::shared_ptr<apache::thrift::protocol::TProtocol> outputProtocol_;
+  std::shared_ptr<apache::thrift::server::TServerEventHandler> eventHandler_;
+  std::shared_ptr<apache::thrift::transport::TTransport> client_;
 
   /**
    * Context acquired from the eventHandler_ if one exists.
diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
index d17f77c..f16fce7 100644
--- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp
+++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
@@ -28,7 +28,11 @@
 #include <algorithm>
 #include <iostream>
 
-#ifdef HAVE_SYS_SELECT_H
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#elif HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#elif HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
 
@@ -80,7 +84,7 @@
 using namespace apache::thrift::concurrency;
 using apache::thrift::transport::TSocket;
 using apache::thrift::transport::TTransportException;
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 /// Three states for sockets: recv frame size, recv data, and send mode
 enum TSocketState { SOCKET_RECV_FRAMING, SOCKET_RECV, SOCKET_SEND };
@@ -115,10 +119,10 @@
   TNonblockingServer* server_;
 
   /// TProcessor
-  stdcxx::shared_ptr<TProcessor> processor_;
+  std::shared_ptr<TProcessor> processor_;
 
   /// Object wrapping network socket
-  stdcxx::shared_ptr<TSocket> tSocket_;
+  std::shared_ptr<TSocket> tSocket_;
 
   /// Libevent object
   struct event event_;
@@ -160,23 +164,23 @@
   int32_t callsForResize_;
 
   /// Transport to read from
-  stdcxx::shared_ptr<TMemoryBuffer> inputTransport_;
+  std::shared_ptr<TMemoryBuffer> inputTransport_;
 
   /// Transport that processor writes to
-  stdcxx::shared_ptr<TMemoryBuffer> outputTransport_;
+  std::shared_ptr<TMemoryBuffer> outputTransport_;
 
   /// extra transport generated by transport factory (e.g. BufferedRouterTransport)
-  stdcxx::shared_ptr<TTransport> factoryInputTransport_;
-  stdcxx::shared_ptr<TTransport> factoryOutputTransport_;
+  std::shared_ptr<TTransport> factoryInputTransport_;
+  std::shared_ptr<TTransport> factoryOutputTransport_;
 
   /// Protocol decoder
-  stdcxx::shared_ptr<TProtocol> inputProtocol_;
+  std::shared_ptr<TProtocol> inputProtocol_;
 
   /// Protocol encoder
-  stdcxx::shared_ptr<TProtocol> outputProtocol_;
+  std::shared_ptr<TProtocol> outputProtocol_;
 
   /// Server event handler, if any
-  stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
+  std::shared_ptr<TServerEventHandler> serverEventHandler_;
 
   /// Thrift call context, if any
   void* connectionContext_;
@@ -209,7 +213,7 @@
   class Task;
 
   /// Constructor
-  TConnection(stdcxx::shared_ptr<TSocket> socket,
+  TConnection(std::shared_ptr<TSocket> socket,
               TNonblockingIOThread* ioThread) {
     readBuffer_ = NULL;
     readBufferSize_ = 0;
@@ -245,7 +249,7 @@
   void init(TNonblockingIOThread* ioThread);
 
   /// set socket for connection
-  void setSocket(stdcxx::shared_ptr<TSocket> socket);
+  void setSocket(std::shared_ptr<TSocket> socket);
 
   /**
    * This is called when the application transitions from one state into
@@ -301,10 +305,10 @@
   TAppState getState() const { return appState_; }
 
   /// return the TSocket transport wrapping this network connection
-  stdcxx::shared_ptr<TSocket> getTSocket() const { return tSocket_; }
+  std::shared_ptr<TSocket> getTSocket() const { return tSocket_; }
 
   /// return the server event handler if any
-  stdcxx::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
+  std::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
 
   /// return the Thrift connection context if any
   void* getConnectionContext() { return connectionContext_; }
@@ -312,9 +316,9 @@
 
 class TNonblockingServer::TConnection::Task : public Runnable {
 public:
-  Task(stdcxx::shared_ptr<TProcessor> processor,
-       stdcxx::shared_ptr<TProtocol> input,
-       stdcxx::shared_ptr<TProtocol> output,
+  Task(std::shared_ptr<TProcessor> processor,
+       std::shared_ptr<TProtocol> input,
+       std::shared_ptr<TProtocol> output,
        TConnection* connection)
     : processor_(processor),
       input_(input),
@@ -359,11 +363,11 @@
   TConnection* getTConnection() { return connection_; }
 
 private:
-  stdcxx::shared_ptr<TProcessor> processor_;
-  stdcxx::shared_ptr<TProtocol> input_;
-  stdcxx::shared_ptr<TProtocol> output_;
+  std::shared_ptr<TProcessor> processor_;
+  std::shared_ptr<TProtocol> input_;
+  std::shared_ptr<TProtocol> output_;
   TConnection* connection_;
-  stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
+  std::shared_ptr<TServerEventHandler> serverEventHandler_;
   void* connectionContext_;
 };
 
@@ -410,7 +414,7 @@
   processor_ = server_->getProcessor(inputProtocol_, outputProtocol_, tSocket_);
 }
 
-void TNonblockingServer::TConnection::setSocket(stdcxx::shared_ptr<TSocket> socket) {
+void TNonblockingServer::TConnection::setSocket(std::shared_ptr<TSocket> socket) {
   tSocket_ = socket;
 }
 
@@ -472,6 +476,18 @@
     }
     // size known; now get the rest of the frame
     transition();
+
+    // If the socket has more data than the frame header, continue to work on it. This is not strictly necessary for
+    // regular sockets, because if there is more data, libevent will fire the event handler registered for read
+    // readiness, which will in turn call workSocket(). However, some socket types (such as TSSLSocket) may have the
+    // data sitting in their internal buffers and from libevent's perspective, there is no further data available. In
+    // that case, not having this workSocket() call here would result in a hang as we will never get to work the socket,
+    // despite having more data.
+    if (tSocket_->hasPendingDataToRead())
+    {
+        workSocket();
+    }
+
     return;
 
   case SOCKET_RECV:
@@ -594,7 +610,7 @@
       // We are setting up a Task to do this work and we will wait on it
 
       // Create task and dispatch to the thread manager
-      stdcxx::shared_ptr<Runnable> task = stdcxx::shared_ptr<Runnable>(
+      std::shared_ptr<Runnable> task = std::shared_ptr<Runnable>(
           new Task(processor_, inputProtocol_, outputProtocol_, this));
       // The application is now waiting on the task to finish
       appState_ = APP_WAIT_TASK;
@@ -647,6 +663,7 @@
         return;
       }
     }
+    // fallthrough
 
   // Intentionally fall through here, the call to process has written into
   // the writeBuffer_
@@ -677,9 +694,6 @@
       appState_ = APP_SEND_RESULT;
       setWrite();
 
-      // Try to work the socket immediately
-      // workSocket();
-
       return;
     }
 
@@ -698,6 +712,7 @@
                               server_->getIdleWriteBufferLimit());
       callsForResize_ = 0;
     }
+    // fallthrough
 
   // N.B.: We also intentionally fall through here into the INIT state!
 
@@ -718,9 +733,6 @@
     // Register read event
     setRead();
 
-    // Try to work the socket right away
-    // workSocket();
-
     return;
 
   case APP_READ_FRAME_SIZE:
@@ -753,9 +765,6 @@
     socketState_ = SOCKET_RECV;
     appState_ = APP_READ_REQUEST;
 
-    // Work the socket right away
-    workSocket();
-
     return;
 
   case APP_CLOSE_CONNECTION:
@@ -879,9 +888,9 @@
   // objects and the Thread objects have shared_ptrs to the TNonblockingIOThread
   // objects (as runnable) so these objects will never deallocate without help.
   while (!ioThreads_.empty()) {
-    stdcxx::shared_ptr<TNonblockingIOThread> iot = ioThreads_.back();
+    std::shared_ptr<TNonblockingIOThread> iot = ioThreads_.back();
     ioThreads_.pop_back();
-    iot->setThread(stdcxx::shared_ptr<Thread>());
+    iot->setThread(std::shared_ptr<Thread>());
   }
 }
 
@@ -889,7 +898,7 @@
  * Creates a new connection either by reusing an object off the stack or
  * by allocating a new one entirely
  */
-TNonblockingServer::TConnection* TNonblockingServer::createConnection(stdcxx::shared_ptr<TSocket> socket) {
+TNonblockingServer::TConnection* TNonblockingServer::createConnection(std::shared_ptr<TSocket> socket) {
   // Check the stack
   Guard g(connMutex_);
 
@@ -945,7 +954,7 @@
   assert(fd == serverSocket_);
 
   // Going to accept a new client socket
-  stdcxx::shared_ptr<TSocket> clientSocket;
+  std::shared_ptr<TSocket> clientSocket;
 
   clientSocket = serverTransport_->accept();
   if (clientSocket) {
@@ -1008,13 +1017,13 @@
 }
 
 
-void TNonblockingServer::setThreadManager(stdcxx::shared_ptr<ThreadManager> threadManager) {
+void TNonblockingServer::setThreadManager(std::shared_ptr<ThreadManager> threadManager) {
   threadManager_ = threadManager;
   if (threadManager) {
     threadManager->setExpireCallback(
-        apache::thrift::stdcxx::bind(&TNonblockingServer::expireClose,
+        std::bind(&TNonblockingServer::expireClose,
                                      this,
-                                     apache::thrift::stdcxx::placeholders::_1));
+                                     std::placeholders::_1));
     threadPoolProcessing_ = true;
   } else {
     threadPoolProcessing_ = false;
@@ -1046,7 +1055,7 @@
 
 bool TNonblockingServer::drainPendingTask() {
   if (threadManager_) {
-    stdcxx::shared_ptr<Runnable> task = threadManager_->removeNextPending();
+    std::shared_ptr<Runnable> task = threadManager_->removeNextPending();
     if (task) {
       TConnection* connection = static_cast<TConnection::Task*>(task.get())->getTConnection();
       assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK);
@@ -1057,13 +1066,13 @@
   return false;
 }
 
-void TNonblockingServer::expireClose(stdcxx::shared_ptr<Runnable> task) {
+void TNonblockingServer::expireClose(std::shared_ptr<Runnable> task) {
   TConnection* connection = static_cast<TConnection::Task*>(task.get())->getTConnection();
   assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK);
   connection->forceClose();
 }
 
-void TNonblockingServer::stop() { 
+void TNonblockingServer::stop() {
   // Breaks the event loop in all threads so that they end ASAP.
   for (uint32_t i = 0; i < ioThreads_.size(); ++i) {
     ioThreads_[i]->stop();
@@ -1110,7 +1119,7 @@
   // Launch all the secondary IO threads in separate threads
   if (ioThreads_.size() > 1) {
     ioThreadFactory_.reset(new PlatformThreadFactory(
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
         PlatformThreadFactory::OTHER,  // scheduler
         PlatformThreadFactory::NORMAL, // priority
         1,                             // stack size (MB)
@@ -1286,10 +1295,44 @@
     return false;
   }
 
-  fd_set wfds, efds;
-  long ret = -1;
+  int ret = -1;
   long kSize = sizeof(conn);
-  const char* pos = reinterpret_cast<const char*>(&conn);
+  const char * pos = (const char *)const_cast_sockopt(&conn);
+
+#if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
+  struct pollfd pfd = {fd, POLLOUT, 0};
+
+  while (kSize > 0) {
+    pfd.revents = 0;
+    ret = poll(&pfd, 1, -1);
+    if (ret < 0) {
+      return false;
+    } else if (ret == 0) {
+      continue;
+    }
+
+    if (pfd.revents & POLLHUP || pfd.revents & POLLERR) {
+      ::THRIFT_CLOSESOCKET(fd);
+      return false;
+    }
+
+    if (pfd.revents & POLLOUT) {
+      ret = send(fd, pos, kSize, 0);
+      if (ret < 0) {
+        if (errno == EAGAIN) {
+          continue;
+        }
+
+        ::THRIFT_CLOSESOCKET(fd);
+        return false;
+      }
+
+      kSize -= ret;
+      pos += ret;
+    }
+  }
+#else
+  fd_set wfds, efds;
 
   while (kSize > 0) {
     FD_ZERO(&wfds);
@@ -1323,6 +1366,7 @@
       pos += ret;
     }
   }
+#endif
 
   return true;
 }
diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h
index f95a729..e79c24f 100644
--- a/lib/cpp/src/thrift/server/TNonblockingServer.h
+++ b/lib/cpp/src/thrift/server/TNonblockingServer.h
@@ -21,7 +21,7 @@
 #define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1
 
 #include <thrift/Thrift.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/server/TServer.h>
 #include <thrift/transport/PlatformSocket.h>
 #include <thrift/transport/TBufferTransports.h>
@@ -160,16 +160,16 @@
   event_base* userEventBase_;
 
   /// For processing via thread pool, may be NULL
-  stdcxx::shared_ptr<ThreadManager> threadManager_;
+  std::shared_ptr<ThreadManager> threadManager_;
 
   /// Is thread pool processing?
   bool threadPoolProcessing_;
 
   // Factory to create the IO threads
-  stdcxx::shared_ptr<PlatformThreadFactory> ioThreadFactory_;
+  std::shared_ptr<PlatformThreadFactory> ioThreadFactory_;
 
   // Vector of IOThread objects that will handle our IO
-  std::vector<stdcxx::shared_ptr<TNonblockingIOThread> > ioThreads_;
+  std::vector<std::shared_ptr<TNonblockingIOThread> > ioThreads_;
 
   // Index of next IO Thread to be used (for round-robin)
   uint32_t nextIOThread_;
@@ -264,7 +264,7 @@
 
   /*
   */
-  stdcxx::shared_ptr<TNonblockingServerTransport> serverTransport_;
+  std::shared_ptr<TNonblockingServerTransport> serverTransport_;
 
   /**
    * Called when server socket had something happen.  We accept all waiting
@@ -301,24 +301,24 @@
   }
 
 public:
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
+  TNonblockingServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
     : TServer(processorFactory), serverTransport_(serverTransport) {
     init();
   }
 
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
+  TNonblockingServer(const std::shared_ptr<TProcessor>& processor,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport)
     : TServer(processor), serverTransport_(serverTransport) {
     init();
   }
 
 
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-                     const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
-                     const stdcxx::shared_ptr<ThreadManager>& threadManager
-                     = stdcxx::shared_ptr<ThreadManager>())
+  TNonblockingServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+                     const std::shared_ptr<TProtocolFactory>& protocolFactory,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
+                     const std::shared_ptr<ThreadManager>& threadManager
+                     = std::shared_ptr<ThreadManager>())
     : TServer(processorFactory), serverTransport_(serverTransport) {
     init();
 
@@ -327,11 +327,11 @@
     setThreadManager(threadManager);
   }
 
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
-                     const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
-                     const stdcxx::shared_ptr<ThreadManager>& threadManager
-                     = stdcxx::shared_ptr<ThreadManager>())
+  TNonblockingServer(const std::shared_ptr<TProcessor>& processor,
+                     const std::shared_ptr<TProtocolFactory>& protocolFactory,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
+                     const std::shared_ptr<ThreadManager>& threadManager
+                     = std::shared_ptr<ThreadManager>())
     : TServer(processor), serverTransport_(serverTransport) {
     init();
 
@@ -340,14 +340,14 @@
     setThreadManager(threadManager);
   }
 
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-                     const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
-                     const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
-                     const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
-                     const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
-                     const stdcxx::shared_ptr<ThreadManager>& threadManager
-                     = stdcxx::shared_ptr<ThreadManager>())
+  TNonblockingServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+                     const std::shared_ptr<TTransportFactory>& inputTransportFactory,
+                     const std::shared_ptr<TTransportFactory>& outputTransportFactory,
+                     const std::shared_ptr<TProtocolFactory>& inputProtocolFactory,
+                     const std::shared_ptr<TProtocolFactory>& outputProtocolFactory,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
+                     const std::shared_ptr<ThreadManager>& threadManager
+                     = std::shared_ptr<ThreadManager>())
     : TServer(processorFactory), serverTransport_(serverTransport) {
     init();
 
@@ -358,14 +358,14 @@
     setThreadManager(threadManager);
   }
 
-  TNonblockingServer(const stdcxx::shared_ptr<TProcessor>& processor,
-                     const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
-                     const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
-                     const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
-                     const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory,
-                     const stdcxx::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
-                     const stdcxx::shared_ptr<ThreadManager>& threadManager
-                     = stdcxx::shared_ptr<ThreadManager>())
+  TNonblockingServer(const std::shared_ptr<TProcessor>& processor,
+                     const std::shared_ptr<TTransportFactory>& inputTransportFactory,
+                     const std::shared_ptr<TTransportFactory>& outputTransportFactory,
+                     const std::shared_ptr<TProtocolFactory>& inputProtocolFactory,
+                     const std::shared_ptr<TProtocolFactory>& outputProtocolFactory,
+                     const std::shared_ptr<apache::thrift::transport::TNonblockingServerTransport>& serverTransport,
+                     const std::shared_ptr<ThreadManager>& threadManager
+                     = std::shared_ptr<ThreadManager>())
     : TServer(processor), serverTransport_(serverTransport) {
     init();
 
@@ -378,11 +378,11 @@
 
   ~TNonblockingServer();
 
-  void setThreadManager(stdcxx::shared_ptr<ThreadManager> threadManager);
+  void setThreadManager(std::shared_ptr<ThreadManager> threadManager);
 
   int getListenPort() { return serverTransport_->getListenPort(); }
 
-  stdcxx::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
+  std::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
 
   /**
    * Sets the number of IO threads used by this server. Can only be used before
@@ -421,7 +421,7 @@
 
   bool isThreadPoolProcessing() const { return threadPoolProcessing_; }
 
-  void addTask(stdcxx::shared_ptr<Runnable> task) {
+  void addTask(std::shared_ptr<Runnable> task) {
     threadManager_->add(task, 0LL, taskExpireTime_);
   }
 
@@ -709,7 +709,7 @@
    *
    * @param task the runnable associated with the expired task.
    */
-  void expireClose(stdcxx::shared_ptr<Runnable> task);
+  void expireClose(std::shared_ptr<Runnable> task);
 
   /**
    * Return an initialized connection object.  Creates or recovers from
@@ -721,7 +721,7 @@
    * @param addrLen the length of addr
    * @return pointer to initialized TConnection object.
    */
-  TConnection* createConnection(stdcxx::shared_ptr<TSocket> socket);
+  TConnection* createConnection(std::shared_ptr<TSocket> socket);
 
   /**
    * Returns a connection to pool or deletion.  If the connection pool
@@ -765,10 +765,10 @@
   evutil_socket_t getNotificationRecvFD() const { return notificationPipeFDs_[0]; }
 
   // Returns the actual thread object associated with this IO thread.
-  stdcxx::shared_ptr<Thread> getThread() const { return thread_; }
+  std::shared_ptr<Thread> getThread() const { return thread_; }
 
   // Sets the actual thread object associated with this IO thread.
-  void setThread(const stdcxx::shared_ptr<Thread>& t) { thread_ = t; }
+  void setThread(const std::shared_ptr<Thread>& t) { thread_ = t; }
 
   // Used by TConnection objects to indicate processing has finished.
   bool notify(TNonblockingServer::TConnection* conn);
@@ -853,7 +853,7 @@
   evutil_socket_t notificationPipeFDs_[2];
 
   /// Actual IO Thread
-  stdcxx::shared_ptr<Thread> thread_;
+  std::shared_ptr<Thread> thread_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/server/TServer.h b/lib/cpp/src/thrift/server/TServer.h
index f4cd7bc..3c6d818 100644
--- a/lib/cpp/src/thrift/server/TServer.h
+++ b/lib/cpp/src/thrift/server/TServer.h
@@ -25,7 +25,7 @@
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/concurrency/Thread.h>
 
-#include <thrift/stdcxx.h>
+#include <memory>
 
 namespace apache {
 namespace thrift {
@@ -58,8 +58,8 @@
   /**
    * Called when a new client has connected and is about to being processing.
    */
-  virtual void* createContext(stdcxx::shared_ptr<TProtocol> input,
-                              stdcxx::shared_ptr<TProtocol> output) {
+  virtual void* createContext(std::shared_ptr<TProtocol> input,
+                              std::shared_ptr<TProtocol> output) {
     (void)input;
     (void)output;
     return NULL;
@@ -70,8 +70,8 @@
    * context.
    */
   virtual void deleteContext(void* serverContext,
-                             stdcxx::shared_ptr<TProtocol> input,
-                             stdcxx::shared_ptr<TProtocol> output) {
+                             std::shared_ptr<TProtocol> input,
+                             std::shared_ptr<TProtocol> output) {
     (void)serverContext;
     (void)input;
     (void)output;
@@ -80,7 +80,7 @@
   /**
    * Called when a client is about to call the processor.
    */
-  virtual void processContext(void* serverContext, stdcxx::shared_ptr<TTransport> transport) {
+  virtual void processContext(void* serverContext, std::shared_ptr<TTransport> transport) {
     (void)serverContext;
     (void)transport;
   }
@@ -107,62 +107,62 @@
   // Allows running the server as a Runnable thread
   virtual void run() { serve(); }
 
-  stdcxx::shared_ptr<TProcessorFactory> getProcessorFactory() { return processorFactory_; }
+  std::shared_ptr<TProcessorFactory> getProcessorFactory() { return processorFactory_; }
 
-  stdcxx::shared_ptr<TServerTransport> getServerTransport() { return serverTransport_; }
+  std::shared_ptr<TServerTransport> getServerTransport() { return serverTransport_; }
 
-  stdcxx::shared_ptr<TTransportFactory> getInputTransportFactory() { return inputTransportFactory_; }
+  std::shared_ptr<TTransportFactory> getInputTransportFactory() { return inputTransportFactory_; }
 
-  stdcxx::shared_ptr<TTransportFactory> getOutputTransportFactory() {
+  std::shared_ptr<TTransportFactory> getOutputTransportFactory() {
     return outputTransportFactory_;
   }
 
-  stdcxx::shared_ptr<TProtocolFactory> getInputProtocolFactory() { return inputProtocolFactory_; }
+  std::shared_ptr<TProtocolFactory> getInputProtocolFactory() { return inputProtocolFactory_; }
 
-  stdcxx::shared_ptr<TProtocolFactory> getOutputProtocolFactory() { return outputProtocolFactory_; }
+  std::shared_ptr<TProtocolFactory> getOutputProtocolFactory() { return outputProtocolFactory_; }
 
-  stdcxx::shared_ptr<TServerEventHandler> getEventHandler() { return eventHandler_; }
+  std::shared_ptr<TServerEventHandler> getEventHandler() { return eventHandler_; }
 
 protected:
-  TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory)
+  TServer(const std::shared_ptr<TProcessorFactory>& processorFactory)
     : processorFactory_(processorFactory) {
-    setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
-    setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setInputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setOutputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setInputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
   }
 
-  TServer(const stdcxx::shared_ptr<TProcessor>& processor)
+  TServer(const std::shared_ptr<TProcessor>& processor)
     : processorFactory_(new TSingletonProcessorFactory(processor)) {
-    setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
-    setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setInputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setOutputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setInputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
   }
 
-  TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport)
+  TServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+          const std::shared_ptr<TServerTransport>& serverTransport)
     : processorFactory_(processorFactory), serverTransport_(serverTransport) {
-    setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
-    setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setInputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setOutputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setInputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
   }
 
-  TServer(const stdcxx::shared_ptr<TProcessor>& processor,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport)
+  TServer(const std::shared_ptr<TProcessor>& processor,
+          const std::shared_ptr<TServerTransport>& serverTransport)
     : processorFactory_(new TSingletonProcessorFactory(processor)),
       serverTransport_(serverTransport) {
-    setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory>(new TTransportFactory()));
-    setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
-    setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setInputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setOutputTransportFactory(std::shared_ptr<TTransportFactory>(new TTransportFactory()));
+    setInputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
+    setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory()));
   }
 
-  TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport,
-          const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory)
+  TServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+          const std::shared_ptr<TServerTransport>& serverTransport,
+          const std::shared_ptr<TTransportFactory>& transportFactory,
+          const std::shared_ptr<TProtocolFactory>& protocolFactory)
     : processorFactory_(processorFactory),
       serverTransport_(serverTransport),
       inputTransportFactory_(transportFactory),
@@ -170,10 +170,10 @@
       inputProtocolFactory_(protocolFactory),
       outputProtocolFactory_(protocolFactory) {}
 
-  TServer(const stdcxx::shared_ptr<TProcessor>& processor,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport,
-          const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory)
+  TServer(const std::shared_ptr<TProcessor>& processor,
+          const std::shared_ptr<TServerTransport>& serverTransport,
+          const std::shared_ptr<TTransportFactory>& transportFactory,
+          const std::shared_ptr<TProtocolFactory>& protocolFactory)
     : processorFactory_(new TSingletonProcessorFactory(processor)),
       serverTransport_(serverTransport),
       inputTransportFactory_(transportFactory),
@@ -181,12 +181,12 @@
       inputProtocolFactory_(protocolFactory),
       outputProtocolFactory_(protocolFactory) {}
 
-  TServer(const stdcxx::shared_ptr<TProcessorFactory>& processorFactory,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport,
-          const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
-          const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory)
+  TServer(const std::shared_ptr<TProcessorFactory>& processorFactory,
+          const std::shared_ptr<TServerTransport>& serverTransport,
+          const std::shared_ptr<TTransportFactory>& inputTransportFactory,
+          const std::shared_ptr<TTransportFactory>& outputTransportFactory,
+          const std::shared_ptr<TProtocolFactory>& inputProtocolFactory,
+          const std::shared_ptr<TProtocolFactory>& outputProtocolFactory)
     : processorFactory_(processorFactory),
       serverTransport_(serverTransport),
       inputTransportFactory_(inputTransportFactory),
@@ -194,12 +194,12 @@
       inputProtocolFactory_(inputProtocolFactory),
       outputProtocolFactory_(outputProtocolFactory) {}
 
-  TServer(const stdcxx::shared_ptr<TProcessor>& processor,
-          const stdcxx::shared_ptr<TServerTransport>& serverTransport,
-          const stdcxx::shared_ptr<TTransportFactory>& inputTransportFactory,
-          const stdcxx::shared_ptr<TTransportFactory>& outputTransportFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& inputProtocolFactory,
-          const stdcxx::shared_ptr<TProtocolFactory>& outputProtocolFactory)
+  TServer(const std::shared_ptr<TProcessor>& processor,
+          const std::shared_ptr<TServerTransport>& serverTransport,
+          const std::shared_ptr<TTransportFactory>& inputTransportFactory,
+          const std::shared_ptr<TTransportFactory>& outputTransportFactory,
+          const std::shared_ptr<TProtocolFactory>& inputProtocolFactory,
+          const std::shared_ptr<TProtocolFactory>& outputProtocolFactory)
     : processorFactory_(new TSingletonProcessorFactory(processor)),
       serverTransport_(serverTransport),
       inputTransportFactory_(inputTransportFactory),
@@ -214,9 +214,9 @@
    * call).  This allows the TProcessorFactory to return a different processor
    * for each connection if it desires.
    */
-  stdcxx::shared_ptr<TProcessor> getProcessor(stdcxx::shared_ptr<TProtocol> inputProtocol,
-                                             stdcxx::shared_ptr<TProtocol> outputProtocol,
-                                             stdcxx::shared_ptr<TTransport> transport) {
+  std::shared_ptr<TProcessor> getProcessor(std::shared_ptr<TProtocol> inputProtocol,
+                                             std::shared_ptr<TProtocol> outputProtocol,
+                                             std::shared_ptr<TTransport> transport) {
     TConnectionInfo connInfo;
     connInfo.input = inputProtocol;
     connInfo.output = outputProtocol;
@@ -225,35 +225,35 @@
   }
 
   // Class variables
-  stdcxx::shared_ptr<TProcessorFactory> processorFactory_;
-  stdcxx::shared_ptr<TServerTransport> serverTransport_;
+  std::shared_ptr<TProcessorFactory> processorFactory_;
+  std::shared_ptr<TServerTransport> serverTransport_;
 
-  stdcxx::shared_ptr<TTransportFactory> inputTransportFactory_;
-  stdcxx::shared_ptr<TTransportFactory> outputTransportFactory_;
+  std::shared_ptr<TTransportFactory> inputTransportFactory_;
+  std::shared_ptr<TTransportFactory> outputTransportFactory_;
 
-  stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory_;
-  stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory_;
+  std::shared_ptr<TProtocolFactory> inputProtocolFactory_;
+  std::shared_ptr<TProtocolFactory> outputProtocolFactory_;
 
-  stdcxx::shared_ptr<TServerEventHandler> eventHandler_;
+  std::shared_ptr<TServerEventHandler> eventHandler_;
 
 public:
-  void setInputTransportFactory(stdcxx::shared_ptr<TTransportFactory> inputTransportFactory) {
+  void setInputTransportFactory(std::shared_ptr<TTransportFactory> inputTransportFactory) {
     inputTransportFactory_ = inputTransportFactory;
   }
 
-  void setOutputTransportFactory(stdcxx::shared_ptr<TTransportFactory> outputTransportFactory) {
+  void setOutputTransportFactory(std::shared_ptr<TTransportFactory> outputTransportFactory) {
     outputTransportFactory_ = outputTransportFactory;
   }
 
-  void setInputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory) {
+  void setInputProtocolFactory(std::shared_ptr<TProtocolFactory> inputProtocolFactory) {
     inputProtocolFactory_ = inputProtocolFactory;
   }
 
-  void setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory) {
+  void setOutputProtocolFactory(std::shared_ptr<TProtocolFactory> outputProtocolFactory) {
     outputProtocolFactory_ = outputProtocolFactory;
   }
 
-  void setServerEventHandler(stdcxx::shared_ptr<TServerEventHandler> eventHandler) {
+  void setServerEventHandler(std::shared_ptr<TServerEventHandler> eventHandler) {
     eventHandler_ = eventHandler;
   }
 };
diff --git a/lib/cpp/src/thrift/server/TServerFramework.cpp b/lib/cpp/src/thrift/server/TServerFramework.cpp
index ae38336..cbeaa24 100644
--- a/lib/cpp/src/thrift/server/TServerFramework.cpp
+++ b/lib/cpp/src/thrift/server/TServerFramework.cpp
@@ -29,8 +29,8 @@
 using apache::thrift::concurrency::Synchronized;
 using apache::thrift::protocol::TProtocol;
 using apache::thrift::protocol::TProtocolFactory;
-using apache::thrift::stdcxx::bind;
-using apache::thrift::stdcxx::shared_ptr;
+using std::bind;
+using std::shared_ptr;
 using apache::thrift::transport::TServerTransport;
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
@@ -161,7 +161,7 @@
                                outputProtocol,
                                eventHandler_,
                                client),
-          bind(&TServerFramework::disposeConnectedClient, this, stdcxx::placeholders::_1)));
+          bind(&TServerFramework::disposeConnectedClient, this, std::placeholders::_1)));
 
     } catch (TTransportException& ttx) {
       releaseOneDescriptor("inputTransport", inputTransport);
diff --git a/lib/cpp/src/thrift/server/TServerFramework.h b/lib/cpp/src/thrift/server/TServerFramework.h
index 706fd49..eaacce5 100644
--- a/lib/cpp/src/thrift/server/TServerFramework.h
+++ b/lib/cpp/src/thrift/server/TServerFramework.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_
 #define _THRIFT_SERVER_TSERVERFRAMEWORK_H_ 1
 
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <stdint.h>
 #include <thrift/TProcessor.h>
 #include <thrift/concurrency/Monitor.h>
@@ -48,32 +48,32 @@
 class TServerFramework : public TServer {
 public:
   TServerFramework(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
 
   TServerFramework(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
 
   TServerFramework(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
 
   TServerFramework(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
 
   virtual ~TServerFramework();
 
@@ -130,7 +130,7 @@
    *
    * \param[in]  pClient  the newly connected client
    */
-  virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) = 0;
+  virtual void onClientConnected(const std::shared_ptr<TConnectedClient>& pClient) = 0;
 
   /**
    * A client has disconnected.
@@ -149,7 +149,7 @@
    * client rate limiting after onClientConnected returns by blocking the
    * serve() thread if the limit has been reached.
    */
-  void newlyConnectedClient(const stdcxx::shared_ptr<TConnectedClient>& pClient);
+  void newlyConnectedClient(const std::shared_ptr<TConnectedClient>& pClient);
 
   /**
    * Smart pointer client deletion.
diff --git a/lib/cpp/src/thrift/server/TSimpleServer.cpp b/lib/cpp/src/thrift/server/TSimpleServer.cpp
index a0afbbe..716234d 100644
--- a/lib/cpp/src/thrift/server/TSimpleServer.cpp
+++ b/lib/cpp/src/thrift/server/TSimpleServer.cpp
@@ -29,7 +29,7 @@
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
 using apache::thrift::transport::TTransportFactory;
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::string;
 
 TSimpleServer::TSimpleServer(const shared_ptr<TProcessorFactory>& processorFactory,
diff --git a/lib/cpp/src/thrift/server/TSimpleServer.h b/lib/cpp/src/thrift/server/TSimpleServer.h
index ac4ed34..4549225 100644
--- a/lib/cpp/src/thrift/server/TSimpleServer.h
+++ b/lib/cpp/src/thrift/server/TSimpleServer.h
@@ -34,37 +34,37 @@
 class TSimpleServer : public TServerFramework {
 public:
   TSimpleServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
 
   TSimpleServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory);
 
   TSimpleServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
 
   TSimpleServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory);
 
   virtual ~TSimpleServer();
 
 protected:
-  virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
+  virtual void onClientConnected(const std::shared_ptr<TConnectedClient>& pClient) /* override */;
   virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
 
 private:
diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
index f07ff84..ee345a9 100644
--- a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
+++ b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
@@ -30,7 +30,7 @@
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
 using apache::thrift::transport::TTransportFactory;
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::string;
 
 TThreadPoolServer::TThreadPoolServer(const shared_ptr<TProcessorFactory>& processorFactory,
@@ -115,7 +115,7 @@
   taskExpiration_ = value;
 }
 
-stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>
+std::shared_ptr<apache::thrift::concurrency::ThreadManager>
 TThreadPoolServer::getThreadManager() const {
   return threadManager_;
 }
diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h
index 94088d5..121998c 100644
--- a/lib/cpp/src/thrift/server/TThreadPoolServer.h
+++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h
@@ -20,7 +20,7 @@
 #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_
 #define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1
 
-#include <boost/atomic.hpp>
+#include <atomic>
 #include <thrift/concurrency/ThreadManager.h>
 #include <thrift/server/TServerFramework.h>
 
@@ -34,39 +34,39 @@
 class TThreadPoolServer : public TServerFramework {
 public:
   TThreadPoolServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
       = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
 
   TThreadPoolServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
       = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
 
   TThreadPoolServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
       = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
 
   TThreadPoolServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadManager>& threadManager
       = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager());
 
   virtual ~TThreadPoolServer();
@@ -83,15 +83,15 @@
   virtual int64_t getTaskExpiration() const;
   virtual void setTaskExpiration(int64_t value);
 
-  virtual stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager> getThreadManager() const;
+  virtual std::shared_ptr<apache::thrift::concurrency::ThreadManager> getThreadManager() const;
 
 protected:
-  virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
+  virtual void onClientConnected(const std::shared_ptr<TConnectedClient>& pClient) /* override */;
   virtual void onClientDisconnected(TConnectedClient* pClient) /* override */;
 
-  stdcxx::shared_ptr<apache::thrift::concurrency::ThreadManager> threadManager_;
-  boost::atomic<int64_t> timeout_;
-  boost::atomic<int64_t> taskExpiration_;
+  std::shared_ptr<apache::thrift::concurrency::ThreadManager> threadManager_;
+  std::atomic<int64_t> timeout_;
+  std::atomic<int64_t> taskExpiration_;
 };
 
 }
diff --git a/lib/cpp/src/thrift/server/TThreadedServer.cpp b/lib/cpp/src/thrift/server/TThreadedServer.cpp
index 8a07db9..2264df7 100644
--- a/lib/cpp/src/thrift/server/TThreadedServer.cpp
+++ b/lib/cpp/src/thrift/server/TThreadedServer.cpp
@@ -18,7 +18,7 @@
  */
 
 #include <string>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/concurrency/PlatformThreadFactory.h>
 #include <thrift/server/TThreadedServer.h>
 
@@ -32,8 +32,8 @@
 using apache::thrift::concurrency::ThreadFactory;
 using apache::thrift::protocol::TProtocol;
 using apache::thrift::protocol::TProtocolFactory;
-using apache::thrift::stdcxx::make_shared;
-using apache::thrift::stdcxx::shared_ptr;
+using std::make_shared;
+using std::shared_ptr;
 using apache::thrift::transport::TServerTransport;
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
@@ -126,9 +126,11 @@
   Synchronized sync(clientMonitor_);
   drainDeadClients(); // use the outgoing thread to do some maintenance on our dead client backlog
   ClientMap::iterator it = activeClientMap_.find(pClient);
-  ClientMap::iterator end = it;
-  deadClientMap_.insert(it, ++end);
-  activeClientMap_.erase(it);
+  if (it != activeClientMap_.end()) {
+    ClientMap::iterator end = it;
+    deadClientMap_.insert(it, ++end);
+    activeClientMap_.erase(it);
+  }
   if (activeClientMap_.empty()) {
     clientMonitor_.notify();
   }
diff --git a/lib/cpp/src/thrift/server/TThreadedServer.h b/lib/cpp/src/thrift/server/TThreadedServer.h
index 1e0a824..c5ccd03 100644
--- a/lib/cpp/src/thrift/server/TThreadedServer.h
+++ b/lib/cpp/src/thrift/server/TThreadedServer.h
@@ -38,43 +38,43 @@
 class TThreadedServer : public TServerFramework {
 public:
   TThreadedServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
-      = stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
+      = std::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
           new apache::thrift::concurrency::PlatformThreadFactory(false)));
 
   TThreadedServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
-      = stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& transportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& protocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
+      = std::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
           new apache::thrift::concurrency::PlatformThreadFactory(false)));
 
   TThreadedServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
-      = stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
+      const std::shared_ptr<apache::thrift::TProcessorFactory>& processorFactory,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
+      = std::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
           new apache::thrift::concurrency::PlatformThreadFactory(false)));
 
   TThreadedServer(
-      const stdcxx::shared_ptr<apache::thrift::TProcessor>& processor,
-      const stdcxx::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
-      const stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
-      = stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
+      const std::shared_ptr<apache::thrift::TProcessor>& processor,
+      const std::shared_ptr<apache::thrift::transport::TServerTransport>& serverTransport,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& inputTransportFactory,
+      const std::shared_ptr<apache::thrift::transport::TTransportFactory>& outputTransportFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& inputProtocolFactory,
+      const std::shared_ptr<apache::thrift::protocol::TProtocolFactory>& outputProtocolFactory,
+      const std::shared_ptr<apache::thrift::concurrency::ThreadFactory>& threadFactory
+      = std::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
           new apache::thrift::concurrency::PlatformThreadFactory(false)));
 
   virtual ~TThreadedServer();
@@ -95,14 +95,14 @@
   /**
    * Implementation of TServerFramework::onClientConnected
    */
-  virtual void onClientConnected(const stdcxx::shared_ptr<TConnectedClient>& pClient) /* override */;
+  virtual void onClientConnected(const std::shared_ptr<TConnectedClient>& pClient) /* override */;
 
   /**
    * Implementation of TServerFramework::onClientDisconnected
    */
   virtual void onClientDisconnected(TConnectedClient *pClient) /* override */;
 
-  stdcxx::shared_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory_;
+  std::shared_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory_;
 
   /**
    * A helper wrapper used to wrap the client in something we can use to maintain
@@ -114,16 +114,16 @@
   class TConnectedClientRunner : public apache::thrift::concurrency::Runnable
   {
   public:
-    TConnectedClientRunner(const stdcxx::shared_ptr<TConnectedClient>& pClient);
+    TConnectedClientRunner(const std::shared_ptr<TConnectedClient>& pClient);
     virtual ~TConnectedClientRunner();
     void run() /* override */;
   private:
-    stdcxx::shared_ptr<TConnectedClient> pClient_;
+    std::shared_ptr<TConnectedClient> pClient_;
   };
 
   apache::thrift::concurrency::Monitor clientMonitor_;
 
-  typedef std::map<TConnectedClient *, stdcxx::shared_ptr<apache::thrift::concurrency::Thread> > ClientMap;
+  typedef std::map<TConnectedClient *, std::shared_ptr<apache::thrift::concurrency::Thread> > ClientMap;
 
   /**
    * A map of active clients
diff --git a/lib/cpp/src/thrift/stdcxx.h b/lib/cpp/src/thrift/stdcxx.h
deleted file mode 100644
index 5113940..0000000
--- a/lib/cpp/src/thrift/stdcxx.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _THRIFT_STDCXX_H_
-#define _THRIFT_STDCXX_H_ 1
-
-#include <boost/config.hpp>
-
-///////////////////////////////////////////////////////////////////
-//
-// functional (function, bind)
-//
-///////////////////////////////////////////////////////////////////
-
-#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL)
-#include <boost/tr1/functional.hpp>
-#define _THRIFT_FUNCTIONAL_TR1_ 1
-#endif
-
-#if _THRIFT_FUNCTIONAL_TR1_
-
-  namespace apache { namespace thrift { namespace stdcxx {
-
-    using ::std::tr1::bind;
-    using ::std::tr1::function;
-
-    namespace placeholders {
-      using ::std::tr1::placeholders::_1;
-      using ::std::tr1::placeholders::_2;
-      using ::std::tr1::placeholders::_3;
-      using ::std::tr1::placeholders::_4;
-      using ::std::tr1::placeholders::_5;
-      using ::std::tr1::placeholders::_6;
-      using ::std::tr1::placeholders::_7;
-      using ::std::tr1::placeholders::_8;
-      using ::std::tr1::placeholders::_9;
-    } // apache::thrift::stdcxx::placeholders
-  }}} // apache::thrift::stdcxx
-
-#else
-
-  #include <functional>
-
-  namespace apache { namespace thrift { namespace stdcxx {
-    using ::std::bind;
-    using ::std::function;
-
-    namespace placeholders {
-      using ::std::placeholders::_1;
-      using ::std::placeholders::_2;
-      using ::std::placeholders::_3;
-      using ::std::placeholders::_4;
-      using ::std::placeholders::_5;
-      using ::std::placeholders::_6;
-      using ::std::placeholders::_7;
-      using ::std::placeholders::_8;
-      using ::std::placeholders::_9;
-    } // apache::thrift::stdcxx::placeholders
-  }}} // apache::thrift::stdcxx
-
-#endif
-
-///////////////////////////////////////////////////////////////////
-//
-// Smart Pointers
-//
-///////////////////////////////////////////////////////////////////
-
-// We can use std for memory functions only if the compiler supports template aliasing
-// The macro BOOST_NO_CXX11_SMART_PTR is defined as 1 under Visual Studio 2010 and 2012
-// which do not support the feature, so we must continue to use C++98 and boost on them.
-// We cannot use __cplusplus to detect this either, since Microsoft advertises an older one.
-
-#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR)
-#include <boost/smart_ptr.hpp>
-#else
-#include <memory>
-#endif
-
-namespace apache { namespace thrift { namespace stdcxx {
-
-#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR)
-
-  using ::boost::const_pointer_cast;
-  using ::boost::dynamic_pointer_cast;
-  using ::boost::enable_shared_from_this;
-  using ::boost::make_shared;
-  using ::boost::scoped_ptr;
-  using ::boost::shared_ptr;
-  using ::boost::static_pointer_cast;
-  using ::boost::weak_ptr;
-
-#else
-
-  using ::std::const_pointer_cast;
-  using ::std::dynamic_pointer_cast;
-  using ::std::enable_shared_from_this;
-  using ::std::make_shared;
-  template <typename T> using scoped_ptr = std::unique_ptr<T>;		// compiler must support template aliasing
-  using ::std::shared_ptr;
-  using ::std::static_pointer_cast;
-  using ::std::weak_ptr;
-
-#endif
-
-}}} // apache::thrift::stdcxx
-
-#endif // #ifndef _THRIFT_STDCXX_H_
diff --git a/lib/cpp/src/thrift/transport/PlatformSocket.h b/lib/cpp/src/thrift/transport/PlatformSocket.h
index 1890b60..9591058 100644
--- a/lib/cpp/src/thrift/transport/PlatformSocket.h
+++ b/lib/cpp/src/thrift/transport/PlatformSocket.h
@@ -51,6 +51,8 @@
 #  define THRIFT_LSEEK _lseek
 #  define THRIFT_WRITE _write
 #  define THRIFT_READ _read
+#  define THRIFT_IOCTL_SOCKET ioctlsocket
+#  define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE u_long
 #  define THRIFT_FSTAT _fstat
 #  define THRIFT_STAT _stat
 #  ifdef _WIN32_WCE
@@ -111,6 +113,8 @@
 #  define THRIFT_LSEEK lseek
 #  define THRIFT_WRITE write
 #  define THRIFT_READ read
+#  define THRIFT_IOCTL_SOCKET ioctl
+#  define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE int
 #  define THRIFT_STAT stat
 #  define THRIFT_FSTAT fstat
 #  define THRIFT_GAI_STRERROR gai_strerror
diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.cpp b/lib/cpp/src/thrift/transport/TBufferTransports.cpp
index 1d2692d..9ac2f84 100644
--- a/lib/cpp/src/thrift/transport/TBufferTransports.cpp
+++ b/lib/cpp/src/thrift/transport/TBufferTransports.cpp
@@ -368,7 +368,7 @@
       throw TTransportException(TTransportException::BAD_ARGS,
                                 "Internal buffer size overflow");
     }
-    avail = available_write() + (new_size - bufferSize_);
+    avail = available_write() + (static_cast<uint32_t>(new_size) - bufferSize_);
   }
 
   // Allocate into a new pointer so we don't bork ours if it fails.
@@ -382,7 +382,7 @@
   wBase_ = new_buffer + (wBase_ - buffer_);
   wBound_ = new_buffer + new_size;
   buffer_ = new_buffer;
-  bufferSize_ = new_size;
+  bufferSize_ = static_cast<uint32_t>(new_size);
 }
 
 void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) {
diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h
index 0a4cc6d..c423f9c 100644
--- a/lib/cpp/src/thrift/transport/TBufferTransports.h
+++ b/lib/cpp/src/thrift/transport/TBufferTransports.h
@@ -186,7 +186,7 @@
   static const int DEFAULT_BUFFER_SIZE = 512;
 
   /// Use default buffer sizes.
-  TBufferedTransport(stdcxx::shared_ptr<TTransport> transport)
+  TBufferedTransport(std::shared_ptr<TTransport> transport)
     : transport_(transport),
       rBufSize_(DEFAULT_BUFFER_SIZE),
       wBufSize_(DEFAULT_BUFFER_SIZE),
@@ -196,7 +196,7 @@
   }
 
   /// Use specified buffer sizes.
-  TBufferedTransport(stdcxx::shared_ptr<TTransport> transport, uint32_t sz)
+  TBufferedTransport(std::shared_ptr<TTransport> transport, uint32_t sz)
     : transport_(transport),
       rBufSize_(sz),
       wBufSize_(sz),
@@ -206,7 +206,7 @@
   }
 
   /// Use specified read and write buffer sizes.
-  TBufferedTransport(stdcxx::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz)
+  TBufferedTransport(std::shared_ptr<TTransport> transport, uint32_t rsz, uint32_t wsz)
     : transport_(transport),
       rBufSize_(rsz),
       wBufSize_(wsz),
@@ -255,7 +255,7 @@
    */
   virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
 
-  stdcxx::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
+  std::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
 
   /*
    * TVirtualTransport provides a default implementation of readAll().
@@ -270,7 +270,7 @@
     // Write size never changes.
   }
 
-  stdcxx::shared_ptr<TTransport> transport_;
+  std::shared_ptr<TTransport> transport_;
 
   uint32_t rBufSize_;
   uint32_t wBufSize_;
@@ -291,8 +291,8 @@
   /**
    * Wraps the transport into a buffered one.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TTransport>(new TBufferedTransport(trans));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TTransport>(new TBufferedTransport(trans));
   }
 };
 
@@ -319,7 +319,7 @@
     initPointers();
   }
 
-  TFramedTransport(stdcxx::shared_ptr<TTransport> transport)
+  TFramedTransport(std::shared_ptr<TTransport> transport)
     : transport_(transport),
       rBufSize_(0),
       wBufSize_(DEFAULT_BUFFER_SIZE),
@@ -330,7 +330,7 @@
     initPointers();
   }
 
-  TFramedTransport(stdcxx::shared_ptr<TTransport> transport,
+  TFramedTransport(std::shared_ptr<TTransport> transport,
                    uint32_t sz,
                    uint32_t bufReclaimThresh = (std::numeric_limits<uint32_t>::max)())
     : transport_(transport),
@@ -366,7 +366,7 @@
 
   const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len);
 
-  stdcxx::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
+  std::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
 
   /*
    * TVirtualTransport provides a default implementation of readAll().
@@ -407,7 +407,7 @@
     this->write((uint8_t*)&pad, sizeof(pad));
   }
 
-  stdcxx::shared_ptr<TTransport> transport_;
+  std::shared_ptr<TTransport> transport_;
 
   uint32_t rBufSize_;
   uint32_t wBufSize_;
@@ -430,8 +430,8 @@
   /**
    * Wraps the transport into a framed one.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TTransport>(new TFramedTransport(trans));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TTransport>(new TFramedTransport(trans));
   }
 };
 
@@ -449,13 +449,13 @@
   // Common initialization done by all constructors.
   void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) {
 
-    maxBufferSize_ = std::numeric_limits<uint32_t>::max();
+    maxBufferSize_ = (std::numeric_limits<uint32_t>::max)();
 
     if (buf == NULL && size != 0) {
       assert(owner);
       buf = (uint8_t*)std::malloc(size);
       if (buf == NULL) {
-        throw std::bad_alloc();
+	throw std::bad_alloc();
       }
     }
 
diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp
index 4683f95..afb4411 100644
--- a/lib/cpp/src/thrift/transport/TFileTransport.cpp
+++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp
@@ -25,13 +25,6 @@
 #include <thrift/concurrency/FunctionRunner.h>
 
 #include <boost/version.hpp>
-#if (BOOST_VERSION >= 105700)
-#include <boost/move/unique_ptr.hpp>
-using boost::movelib::unique_ptr;
-#else
-#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
-using boost::interprocess::unique_ptr;
-#endif
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -49,6 +42,7 @@
 #include <cstring>
 #include <iostream>
 #include <limits>
+#include <memory>
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
@@ -61,11 +55,10 @@
 namespace thrift {
 namespace transport {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::cerr;
 using std::cout;
 using std::endl;
-using std::min;
 using std::string;
 using namespace apache::thrift::protocol;
 using namespace apache::thrift::concurrency;
@@ -204,8 +197,6 @@
   enqueueEvent(buf, len);
 }
 
-// this is needed until boost 1.57 as the older unique_ptr implementation
-// has no default deleter in interprocess
 template <class _T>
 struct uniqueDeleter
 {
@@ -229,7 +220,7 @@
     return;
   }
 
-  unique_ptr<eventInfo, uniqueDeleter<eventInfo> > toEnqueue(new eventInfo());
+  std::unique_ptr<eventInfo, uniqueDeleter<eventInfo> > toEnqueue(new eventInfo());
   toEnqueue->eventBuff_ = new uint8_t[(sizeof(uint8_t) * eventLen) + 4];
 
   // first 4 bytes is the event length
@@ -383,7 +374,7 @@
 
         while (hasIOError) {
           T_ERROR(
-              "TFileTransport: writer thread going to sleep for %d microseconds due to IO errors",
+              "TFileTransport: writer thread going to sleep for %u microseconds due to IO errors",
               writerThreadIOErrorSleepTime_);
           THRIFT_SLEEP_USEC(writerThreadIOErrorSleepTime_);
           if (closing_) {
@@ -705,8 +696,8 @@
           readState_.event_->eventBuffPos_ = 0;
         }
         // take either the entire event or the remaining bytes in the buffer
-        int reclaimBuffer = min((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_),
-                                readState_.event_->eventSize_ - readState_.event_->eventBuffPos_);
+        int reclaimBuffer = (std::min)((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_),
+                                       readState_.event_->eventSize_ - readState_.event_->eventBuffPos_);
 
         // copy data from read buffer into event buffer
         memcpy(readState_.event_->eventBuff_ + readState_.event_->eventBuffPos_,
diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h
index d6da436..6cc7bd2 100644
--- a/lib/cpp/src/thrift/transport/TFileTransport.h
+++ b/lib/cpp/src/thrift/transport/TFileTransport.h
@@ -24,12 +24,10 @@
 #include <thrift/Thrift.h>
 #include <thrift/TProcessor.h>
 
+#include <atomic>
 #include <string>
 #include <stdio.h>
 
-#include <boost/atomic.hpp>
-#include <thrift/stdcxx.h>
-
 #include <thrift/concurrency/Mutex.h>
 #include <thrift/concurrency/Monitor.h>
 #include <thrift/concurrency/PlatformThreadFactory.h>
@@ -339,7 +337,7 @@
 
   // writer thread
   apache::thrift::concurrency::PlatformThreadFactory threadFactory_;
-  stdcxx::shared_ptr<apache::thrift::concurrency::Thread> writerThread_;
+  std::shared_ptr<apache::thrift::concurrency::Thread> writerThread_;
 
   // buffers to hold data before it is flushed. Each element of the buffer stores a msg that
   // needs to be written to the file.  The buffers are swapped by the writer thread.
@@ -348,11 +346,11 @@
 
   // conditions used to block when the buffer is full or empty
   Monitor notFull_, notEmpty_;
-  boost::atomic<bool> closing_;
+  std::atomic<bool> closing_;
 
   // To keep track of whether the buffer has been flushed
   Monitor flushed_;
-  boost::atomic<bool> forceFlush_;
+  std::atomic<bool> forceFlush_;
 
   // Mutex that is grabbed when enqueueing and swapping the read/write buffers
   Mutex mutex_;
@@ -390,14 +388,14 @@
    * @param protocolFactory protocol factory
    * @param inputTransport file transport
    */
-  TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
-                 stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
-                 stdcxx::shared_ptr<TFileReaderTransport> inputTransport);
+  TFileProcessor(std::shared_ptr<TProcessor> processor,
+                 std::shared_ptr<TProtocolFactory> protocolFactory,
+                 std::shared_ptr<TFileReaderTransport> inputTransport);
 
-  TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
-                 stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory,
-                 stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory,
-                 stdcxx::shared_ptr<TFileReaderTransport> inputTransport);
+  TFileProcessor(std::shared_ptr<TProcessor> processor,
+                 std::shared_ptr<TProtocolFactory> inputProtocolFactory,
+                 std::shared_ptr<TProtocolFactory> outputProtocolFactory,
+                 std::shared_ptr<TFileReaderTransport> inputTransport);
 
   /**
    * Constructor
@@ -407,10 +405,10 @@
    * @param inputTransport input file transport
    * @param output output transport
    */
-  TFileProcessor(stdcxx::shared_ptr<TProcessor> processor,
-                 stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
-                 stdcxx::shared_ptr<TFileReaderTransport> inputTransport,
-                 stdcxx::shared_ptr<TTransport> outputTransport);
+  TFileProcessor(std::shared_ptr<TProcessor> processor,
+                 std::shared_ptr<TProtocolFactory> protocolFactory,
+                 std::shared_ptr<TFileReaderTransport> inputTransport,
+                 std::shared_ptr<TTransport> outputTransport);
 
   /**
    * processes events from the file
@@ -427,11 +425,11 @@
   void processChunk();
 
 private:
-  stdcxx::shared_ptr<TProcessor> processor_;
-  stdcxx::shared_ptr<TProtocolFactory> inputProtocolFactory_;
-  stdcxx::shared_ptr<TProtocolFactory> outputProtocolFactory_;
-  stdcxx::shared_ptr<TFileReaderTransport> inputTransport_;
-  stdcxx::shared_ptr<TTransport> outputTransport_;
+  std::shared_ptr<TProcessor> processor_;
+  std::shared_ptr<TProtocolFactory> inputProtocolFactory_;
+  std::shared_ptr<TProtocolFactory> outputProtocolFactory_;
+  std::shared_ptr<TFileReaderTransport> inputTransport_;
+  std::shared_ptr<TTransport> outputTransport_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.cpp b/lib/cpp/src/thrift/transport/THeaderTransport.cpp
index 1a687da..25084ec 100644
--- a/lib/cpp/src/thrift/transport/THeaderTransport.cpp
+++ b/lib/cpp/src/thrift/transport/THeaderTransport.cpp
@@ -22,7 +22,6 @@
 #include <thrift/protocol/TProtocolTypes.h>
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/protocol/TCompactProtocol.h>
-#include <thrift/stdcxx.h>
 
 #include <limits>
 #include <utility>
@@ -37,7 +36,7 @@
 namespace apache {
 namespace thrift {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 namespace transport {
 
@@ -511,7 +510,7 @@
 
     // Pkt size
     ptrdiff_t szHbp = (headerStart - pktStart - 4);
-    if (static_cast<uint64_t>(szHbp) > static_cast<uint64_t>(std::numeric_limits<uint32_t>().max()) - (headerSize + haveBytes)) {
+    if (static_cast<uint64_t>(szHbp) > static_cast<uint64_t>((std::numeric_limits<uint32_t>().max)()) - (headerSize + haveBytes)) {
       throw TTransportException(TTransportException::CORRUPTED_DATA,
                                 "Header section size is unreasonable");
     }
diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.h b/lib/cpp/src/thrift/transport/THeaderTransport.h
index 1a2c8e0..e6c57e6 100644
--- a/lib/cpp/src/thrift/transport/THeaderTransport.h
+++ b/lib/cpp/src/thrift/transport/THeaderTransport.h
@@ -34,7 +34,6 @@
 #endif
 
 #include <boost/scoped_array.hpp>
-#include <thrift/stdcxx.h>
 
 #include <thrift/protocol/TProtocolTypes.h>
 #include <thrift/transport/TBufferTransports.h>
@@ -75,7 +74,7 @@
   static const int THRIFT_MAX_VARINT32_BYTES = 5;
 
   /// Use default buffer sizes.
-  explicit THeaderTransport(const stdcxx::shared_ptr<TTransport>& transport)
+  explicit THeaderTransport(const std::shared_ptr<TTransport>& transport)
     : TVirtualTransport(transport),
       outTransport_(transport),
       protoId(T_COMPACT_PROTOCOL),
@@ -88,8 +87,8 @@
     initBuffers();
   }
 
-  THeaderTransport(const stdcxx::shared_ptr<TTransport> inTransport,
-                   const stdcxx::shared_ptr<TTransport> outTransport)
+  THeaderTransport(const std::shared_ptr<TTransport> inTransport,
+                   const std::shared_ptr<TTransport> outTransport)
     : TVirtualTransport(inTransport),
       outTransport_(outTransport),
       protoId(T_COMPACT_PROTOCOL),
@@ -186,7 +185,7 @@
     setWriteBuffer(wBuf_.get(), wBufSize_);
   }
 
-  stdcxx::shared_ptr<TTransport> outTransport_;
+  std::shared_ptr<TTransport> outTransport_;
 
   // 0 and 16th bits must be 0 to differentiate from framed & unframed
   static const uint32_t HEADER_MAGIC = 0x0FFF0000;
@@ -265,8 +264,8 @@
   /**
    * Wraps the transport into a header one.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TTransport>(new THeaderTransport(trans));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TTransport>(new THeaderTransport(trans));
   }
 };
 }
diff --git a/lib/cpp/src/thrift/transport/THttpClient.cpp b/lib/cpp/src/thrift/transport/THttpClient.cpp
index afd02a8..d152197 100644
--- a/lib/cpp/src/thrift/transport/THttpClient.cpp
+++ b/lib/cpp/src/thrift/transport/THttpClient.cpp
@@ -32,14 +32,14 @@
 namespace thrift {
 namespace transport {
 
-THttpClient::THttpClient(stdcxx::shared_ptr<TTransport> transport,
+THttpClient::THttpClient(std::shared_ptr<TTransport> transport,
                          std::string host,
                          std::string path)
   : THttpTransport(transport), host_(host), path_(path) {
 }
 
 THttpClient::THttpClient(string host, int port, string path)
-  : THttpTransport(stdcxx::shared_ptr<TTransport>(new TSocket(host, port))),
+  : THttpTransport(std::shared_ptr<TTransport>(new TSocket(host, port))),
     host_(host),
     path_(path) {
 }
diff --git a/lib/cpp/src/thrift/transport/THttpClient.h b/lib/cpp/src/thrift/transport/THttpClient.h
index 96fd5b8..f4fb12a 100644
--- a/lib/cpp/src/thrift/transport/THttpClient.h
+++ b/lib/cpp/src/thrift/transport/THttpClient.h
@@ -28,7 +28,7 @@
 
 class THttpClient : public THttpTransport {
 public:
-  THttpClient(stdcxx::shared_ptr<TTransport> transport, std::string host, std::string path = "");
+  THttpClient(std::shared_ptr<TTransport> transport, std::string host, std::string path = "");
 
   THttpClient(std::string host, int port, std::string path = "");
 
diff --git a/lib/cpp/src/thrift/transport/THttpServer.cpp b/lib/cpp/src/thrift/transport/THttpServer.cpp
index 2f48cf6..96b2480 100644
--- a/lib/cpp/src/thrift/transport/THttpServer.cpp
+++ b/lib/cpp/src/thrift/transport/THttpServer.cpp
@@ -34,7 +34,7 @@
 namespace thrift {
 namespace transport {
 
-THttpServer::THttpServer(stdcxx::shared_ptr<TTransport> transport) : THttpTransport(transport) {
+THttpServer::THttpServer(std::shared_ptr<TTransport> transport) : THttpTransport(transport) {
 }
 
 THttpServer::~THttpServer() {
diff --git a/lib/cpp/src/thrift/transport/THttpServer.h b/lib/cpp/src/thrift/transport/THttpServer.h
index 086dd6f..c38606f 100644
--- a/lib/cpp/src/thrift/transport/THttpServer.h
+++ b/lib/cpp/src/thrift/transport/THttpServer.h
@@ -28,7 +28,7 @@
 
 class THttpServer : public THttpTransport {
 public:
-  THttpServer(stdcxx::shared_ptr<TTransport> transport);
+  THttpServer(std::shared_ptr<TTransport> transport);
 
   virtual ~THttpServer();
 
@@ -53,8 +53,8 @@
   /**
    * Wraps the transport into a buffered one.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TTransport>(new THttpServer(trans));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TTransport>(new THttpServer(trans));
   }
 };
 }
diff --git a/lib/cpp/src/thrift/transport/THttpTransport.cpp b/lib/cpp/src/thrift/transport/THttpTransport.cpp
index c97f6d3..6ccc034 100644
--- a/lib/cpp/src/thrift/transport/THttpTransport.cpp
+++ b/lib/cpp/src/thrift/transport/THttpTransport.cpp
@@ -31,7 +31,7 @@
 const char* THttpTransport::CRLF = "\r\n";
 const int THttpTransport::CRLF_LEN = 2;
 
-THttpTransport::THttpTransport(stdcxx::shared_ptr<TTransport> transport)
+THttpTransport::THttpTransport(std::shared_ptr<TTransport> transport)
   : transport_(transport),
     origin_(""),
     readHeaders_(true),
@@ -84,8 +84,10 @@
 uint32_t THttpTransport::readMoreData() {
   uint32_t size;
 
-  // Get more data!
-  refill();
+  if (httpPos_ == httpBufLen_) {
+    // Get more data!
+    refill();
+  }
 
   if (readHeaders_) {
     readHeaders();
@@ -200,10 +202,11 @@
   uint32_t avail = httpBufSize_ - httpBufLen_;
   if (avail <= (httpBufSize_ / 4)) {
     httpBufSize_ *= 2;
-    httpBuf_ = (char*)std::realloc(httpBuf_, httpBufSize_ + 1);
-    if (httpBuf_ == NULL) {
+    char* tmpBuf = (char*)std::realloc(httpBuf_, httpBufSize_ + 1);
+    if (tmpBuf == NULL) {
       throw std::bad_alloc();
     }
+    httpBuf_ = tmpBuf;
   }
 
   // Read more data
diff --git a/lib/cpp/src/thrift/transport/THttpTransport.h b/lib/cpp/src/thrift/transport/THttpTransport.h
index 3fa80f8..e46ab7f 100644
--- a/lib/cpp/src/thrift/transport/THttpTransport.h
+++ b/lib/cpp/src/thrift/transport/THttpTransport.h
@@ -36,7 +36,7 @@
  */
 class THttpTransport : public TVirtualTransport<THttpTransport> {
 public:
-  THttpTransport(stdcxx::shared_ptr<TTransport> transport);
+  THttpTransport(std::shared_ptr<TTransport> transport);
 
   virtual ~THttpTransport();
 
@@ -59,7 +59,7 @@
   virtual const std::string getOrigin();
 
 protected:
-  stdcxx::shared_ptr<TTransport> transport_;
+  std::shared_ptr<TTransport> transport_;
   std::string origin_;
 
   TMemoryBuffer writeBuffer_;
diff --git a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp
index da83bea..adec5d0 100644
--- a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp
@@ -27,14 +27,14 @@
 /**
  * Nonblocking SSL server socket implementation.
  */
-TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory)
+TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, std::shared_ptr<TSSLSocketFactory> factory)
   : TNonblockingServerSocket(port), factory_(factory) {
   factory_->server(true);
 }
 
 TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(const std::string& address,
                                    int port,
-                                   stdcxx::shared_ptr<TSSLSocketFactory> factory)
+                                   std::shared_ptr<TSSLSocketFactory> factory)
   : TNonblockingServerSocket(address, port), factory_(factory) {
   factory_->server(true);
 }
@@ -42,13 +42,13 @@
 TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port,
                                    int sendTimeout,
                                    int recvTimeout,
-                                   stdcxx::shared_ptr<TSSLSocketFactory> factory)
+                                   std::shared_ptr<TSSLSocketFactory> factory)
   : TNonblockingServerSocket(port, sendTimeout, recvTimeout), factory_(factory) {
   factory_->server(true);
 }
 
-stdcxx::shared_ptr<TSocket> TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) {
-  stdcxx::shared_ptr<TSSLSocket> tSSLSocket;
+std::shared_ptr<TSocket> TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) {
+  std::shared_ptr<TSSLSocket> tSSLSocket;
   tSSLSocket = factory_->createSocket(client);
   tSSLSocket->setLibeventSafe();
   return tSSLSocket;
diff --git a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h
index 7aaff53..215c405 100644
--- a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h
+++ b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h
@@ -21,7 +21,6 @@
 #define _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_ 1
 
 #include <thrift/transport/TNonblockingServerSocket.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -40,7 +39,7 @@
    * @param port    Listening port
    * @param factory SSL socket factory implementation
    */
-  TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory);
+  TNonblockingSSLServerSocket(int port, std::shared_ptr<TSSLSocketFactory> factory);
 
   /**
    * Constructor.  Binds to the specified address.
@@ -51,7 +50,7 @@
    */
   TNonblockingSSLServerSocket(const std::string& address,
                    int port,
-                   stdcxx::shared_ptr<TSSLSocketFactory> factory);
+                   std::shared_ptr<TSSLSocketFactory> factory);
 
   /**
    * Constructor.  Binds to all interfaces.
@@ -64,11 +63,11 @@
   TNonblockingSSLServerSocket(int port,
                    int sendTimeout,
                    int recvTimeout,
-                   stdcxx::shared_ptr<TSSLSocketFactory> factory);
+                   std::shared_ptr<TSSLSocketFactory> factory);
 
 protected:
-  stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
-  stdcxx::shared_ptr<TSSLSocketFactory> factory_;
+  std::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
+  std::shared_ptr<TSSLSocketFactory> factory_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp
index 89073e1..3d34cca 100644
--- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp
@@ -74,7 +74,7 @@
 namespace transport {
 
 using std::string;
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 TNonblockingServerSocket::TNonblockingServerSocket(int port)
   : port_(port),
@@ -212,7 +212,7 @@
 
   if (!path_.empty()) {
     serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP);
-  } else {
+  } else if (res != NULL) {
     serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
   }
 
diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h
index 1d33239..1586ff0 100644
--- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h
+++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h
@@ -22,7 +22,6 @@
 
 #include <thrift/transport/TNonblockingServerTransport.h>
 #include <thrift/transport/PlatformSocket.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -37,7 +36,7 @@
  */
 class TNonblockingServerSocket : public TNonblockingServerTransport {
 public:
-  typedef apache::thrift::stdcxx::function<void(THRIFT_SOCKET fd)> socket_func_t;
+  typedef std::function<void(THRIFT_SOCKET fd)> socket_func_t;
 
   const static int DEFAULT_BACKLOG = 1024;
 
@@ -108,8 +107,8 @@
   void close();
 
 protected:
-  apache::thrift::stdcxx::shared_ptr<TSocket> acceptImpl();
-  virtual apache::thrift::stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
+  std::shared_ptr<TSocket> acceptImpl();
+  virtual std::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
 
 private:
   int port_;
diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h
index c32a051..3142e19 100644
--- a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h
+++ b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h
@@ -22,7 +22,6 @@
 
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TTransportException.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -56,8 +55,8 @@
    * @return A new TTransport object
    * @throws TTransportException if there is an error
    */
-  stdcxx::shared_ptr<TSocket> accept() {
-    stdcxx::shared_ptr<TSocket> result = acceptImpl();
+  std::shared_ptr<TSocket> accept() {
+    std::shared_ptr<TSocket> result = acceptImpl();
     if (!result) {
       throw TTransportException("accept() may not return NULL");
     }
@@ -91,7 +90,7 @@
    * @return A newly allocated TTransport object
    * @throw TTransportException If an error occurs
    */
-  virtual stdcxx::shared_ptr<TSocket> acceptImpl() = 0;
+  virtual std::shared_ptr<TSocket> acceptImpl() = 0;
 
 };
 }
diff --git a/lib/cpp/src/thrift/transport/TPipe.h b/lib/cpp/src/thrift/transport/TPipe.h
index dfc5f2c..aa14f95 100644
--- a/lib/cpp/src/thrift/transport/TPipe.h
+++ b/lib/cpp/src/thrift/transport/TPipe.h
@@ -95,7 +95,7 @@
   HANDLE getNativeWaitHandle();
 
 private:
-  stdcxx::shared_ptr<TPipeImpl> impl_;
+  std::shared_ptr<TPipeImpl> impl_;
 
   std::string pipename_;
 
diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp
index 5923a62..55c3580 100644
--- a/lib/cpp/src/thrift/transport/TPipeServer.cpp
+++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp
@@ -22,7 +22,6 @@
 
 #include <thrift/transport/TPipe.h>
 #include <thrift/transport/TPipeServer.h>
-#include <thrift/stdcxx.h>
 #include <boost/noncopyable.hpp>
 
 #ifdef _WIN32
@@ -37,14 +36,14 @@
 
 #ifdef _WIN32
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 class TPipeServerImpl : boost::noncopyable {
 public:
   TPipeServerImpl() {}
   virtual ~TPipeServerImpl() {}
   virtual void interrupt() = 0;
-  virtual stdcxx::shared_ptr<TTransport> acceptImpl() = 0;
+  virtual std::shared_ptr<TTransport> acceptImpl() = 0;
 
   virtual HANDLE getPipeHandle() = 0;
   virtual HANDLE getWrtPipeHandle() = 0;
@@ -75,7 +74,7 @@
 
   virtual void interrupt() {} // not currently implemented
 
-  virtual stdcxx::shared_ptr<TTransport> acceptImpl();
+  virtual std::shared_ptr<TTransport> acceptImpl();
 
   virtual HANDLE getPipeHandle() { return PipeR_.h; }
   virtual HANDLE getWrtPipeHandle() { return PipeW_.h; }
@@ -117,7 +116,7 @@
     }
   }
 
-  virtual stdcxx::shared_ptr<TTransport> acceptImpl();
+  virtual std::shared_ptr<TTransport> acceptImpl();
 
   virtual HANDLE getPipeHandle() { return Pipe_.h; }
   virtual HANDLE getWrtPipeHandle() { return INVALID_HANDLE_VALUE; }
@@ -141,7 +140,7 @@
 
   TCriticalSection pipe_protect_;
   // only read or write these variables underneath a locked pipe_protect_
-  stdcxx::shared_ptr<TPipe> cached_client_;
+  std::shared_ptr<TPipe> cached_client_;
   TAutoHandle Pipe_;
 };
 
diff --git a/lib/cpp/src/thrift/transport/TPipeServer.h b/lib/cpp/src/thrift/transport/TPipeServer.h
index 117773c..c9b13e5 100644
--- a/lib/cpp/src/thrift/transport/TPipeServer.h
+++ b/lib/cpp/src/thrift/transport/TPipeServer.h
@@ -20,8 +20,8 @@
 #ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_
 #define _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ 1
 
+#include <memory>
 #include <thrift/transport/TServerTransport.h>
-#include <thrift/stdcxx.h>
 #ifndef _WIN32
 #include <thrift/transport/TServerSocket.h>
 #endif
@@ -82,10 +82,10 @@
   HANDLE getNativeWaitHandle();
 
 protected:
-  virtual stdcxx::shared_ptr<TTransport> acceptImpl();
+  virtual std::shared_ptr<TTransport> acceptImpl();
 
 private:
-  stdcxx::shared_ptr<TPipeServerImpl> impl_;
+  std::shared_ptr<TPipeServerImpl> impl_;
 
   std::string pipename_;
   uint32_t bufsize_;
diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp
index 8e81ad7..34605c0 100644
--- a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp
@@ -27,14 +27,14 @@
 /**
  * SSL server socket implementation.
  */
-TSSLServerSocket::TSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory)
+TSSLServerSocket::TSSLServerSocket(int port, std::shared_ptr<TSSLSocketFactory> factory)
   : TServerSocket(port), factory_(factory) {
   factory_->server(true);
 }
 
 TSSLServerSocket::TSSLServerSocket(const std::string& address,
                                    int port,
-                                   stdcxx::shared_ptr<TSSLSocketFactory> factory)
+                                   std::shared_ptr<TSSLSocketFactory> factory)
   : TServerSocket(address, port), factory_(factory) {
   factory_->server(true);
 }
@@ -42,12 +42,12 @@
 TSSLServerSocket::TSSLServerSocket(int port,
                                    int sendTimeout,
                                    int recvTimeout,
-                                   stdcxx::shared_ptr<TSSLSocketFactory> factory)
+                                   std::shared_ptr<TSSLSocketFactory> factory)
   : TServerSocket(port, sendTimeout, recvTimeout), factory_(factory) {
   factory_->server(true);
 }
 
-stdcxx::shared_ptr<TSocket> TSSLServerSocket::createSocket(THRIFT_SOCKET client) {
+std::shared_ptr<TSocket> TSSLServerSocket::createSocket(THRIFT_SOCKET client) {
   if (interruptableChildren_) {
       return factory_->createSocket(client, pChildInterruptSockReader_);
 
diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.h b/lib/cpp/src/thrift/transport/TSSLServerSocket.h
index dda9af4..8b75de8 100644
--- a/lib/cpp/src/thrift/transport/TSSLServerSocket.h
+++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.h
@@ -20,7 +20,6 @@
 #ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_
 #define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1
 
-#include <thrift/stdcxx.h>
 #include <thrift/transport/TServerSocket.h>
 
 namespace apache {
@@ -40,7 +39,7 @@
    * @param port    Listening port
    * @param factory SSL socket factory implementation
    */
-  TSSLServerSocket(int port, stdcxx::shared_ptr<TSSLSocketFactory> factory);
+  TSSLServerSocket(int port, std::shared_ptr<TSSLSocketFactory> factory);
 
   /**
    * Constructor.  Binds to the specified address.
@@ -51,7 +50,7 @@
    */
   TSSLServerSocket(const std::string& address,
                    int port,
-                   stdcxx::shared_ptr<TSSLSocketFactory> factory);
+                   std::shared_ptr<TSSLSocketFactory> factory);
 
   /**
    * Constructor.  Binds to all interfaces.
@@ -64,11 +63,11 @@
   TSSLServerSocket(int port,
                    int sendTimeout,
                    int recvTimeout,
-                   stdcxx::shared_ptr<TSSLSocketFactory> factory);
+                   std::shared_ptr<TSSLSocketFactory> factory);
 
 protected:
-  stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
-  stdcxx::shared_ptr<TSSLSocketFactory> factory_;
+  std::shared_ptr<TSocket> createSocket(THRIFT_SOCKET socket);
+  std::shared_ptr<TSSLSocketFactory> factory_;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
index 3f0e28e..718e9b1 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
@@ -213,33 +213,33 @@
 }
 
 // TSSLSocket implementation
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx)
   : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
 }
 
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx, std::shared_ptr<THRIFT_SOCKET> interruptListener)
         : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
   interruptListener_ = interruptListener;
 }
 
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket)
   : TSocket(socket), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
 }
 
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener)
         : TSocket(socket, interruptListener), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
 }
 
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, string host, int port)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx, string host, int port)
   : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
 }
 
-TSSLSocket::TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, string host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
+TSSLSocket::TSSLSocket(std::shared_ptr<SSLContext> ctx, string host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener)
         : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) {
   init();
   interruptListener_ = interruptListener;
@@ -249,6 +249,17 @@
   close();
 }
 
+bool TSSLSocket::hasPendingDataToRead() {
+  if (!isOpen()) {
+    return false;
+  }
+  initializeHandshake();
+  if (!checkHandshake())
+    throw TSSLException("TSSLSocket::hasPendingDataToRead: Handshake is not completed");
+  // data may be available in SSL buffers (note: SSL_pending does not have a failure mode)
+  return SSL_pending(ssl_) > 0 || TSocket::hasPendingDataToRead();
+}
+
 void TSSLSocket::init() {
   handshakeCompleted_ = false;
   readRetryCount_ = 0;
@@ -293,6 +304,7 @@
               && (errno_copy != THRIFT_EAGAIN)) {
             break;
           }
+        // fallthrough
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_WRITE:
           // in the case of SSL_ERROR_SYSCALL we want to wait for an read event again
@@ -339,6 +351,7 @@
                   && (errno_copy != THRIFT_EAGAIN)) {
                 break;
               }
+            // fallthrough
             case SSL_ERROR_WANT_READ:
             case SSL_ERROR_WANT_WRITE:
               // in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again
@@ -390,11 +403,16 @@
       break;
     }
     unsigned int waitEventReturn;
+    bool breakout = false;
     switch (error) {
       case SSL_ERROR_ZERO_RETURN:
         throw TTransportException(TTransportException::END_OF_FILE, "client disconnected");
 
       case SSL_ERROR_SYSCALL:
+        if (errno_copy == 0 && ERR_peek_error() == 0) {
+          breakout = true;
+          break;
+        }
         if ((errno_copy != THRIFT_EINTR)
             && (errno_copy != THRIFT_EAGAIN)) {
               break;
@@ -404,6 +422,8 @@
           // a certain number
           break;
         }
+      // fallthrough
+
       case SSL_ERROR_WANT_READ:
       case SSL_ERROR_WANT_WRITE:
         if (isLibeventSafe()) {
@@ -435,6 +455,9 @@
         throw TTransportException(TTransportException::INTERNAL_ERROR, "unkown waitForEvent return value");
       default:;// do nothing
     }
+    if (breakout) {
+      break;
+    }
     string errors;
     buildErrors(errors, errno_copy, error);
     throw TSSLException("SSL_read: " + errors);
@@ -460,6 +483,7 @@
               && (errno_copy != THRIFT_EAGAIN)) {
             break;
           }
+        // fallthrough        
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_WRITE:
           if (isLibeventSafe()) {
@@ -504,6 +528,7 @@
               && (errno_copy != THRIFT_EAGAIN)) {
             break;
           }
+        // fallthrough
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_WRITE:
           if (isLibeventSafe()) {
@@ -591,6 +616,7 @@
                 && (errno_copy != THRIFT_EAGAIN)) {
               break;
             }
+          // fallthrough
           case SSL_ERROR_WANT_READ:
           case SSL_ERROR_WANT_WRITE:
             if (isLibeventSafe()) {
@@ -623,6 +649,7 @@
                 && (errno_copy != THRIFT_EAGAIN)) {
               break;
             }
+          // fallthrough
           case SSL_ERROR_WANT_READ:
           case SSL_ERROR_WANT_WRITE:
             if (isLibeventSafe()) {
@@ -830,7 +857,7 @@
     randomize();
   }
   count_++;
-  ctx_ = stdcxx::shared_ptr<SSLContext>(new SSLContext(protocol));
+  ctx_ = std::shared_ptr<SSLContext>(new SSLContext(protocol));
 }
 
 TSSLSocketFactory::~TSSLSocketFactory() {
@@ -842,47 +869,47 @@
   }
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket() {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket() {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_));
   setup(ssl);
   return ssl;
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, interruptListener));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(std::shared_ptr<THRIFT_SOCKET> interruptListener) {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, interruptListener));
   setup(ssl);
   return ssl;
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket));
   setup(ssl);
   return ssl;
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket, interruptListener));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener) {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, socket, interruptListener));
   setup(ssl);
   return ssl;
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port) {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port) {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port));
   setup(ssl);
   return ssl;
 }
 
-stdcxx::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener) {
-  stdcxx::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port, interruptListener));
+std::shared_ptr<TSSLSocket> TSSLSocketFactory::createSocket(const string& host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener) {
+  std::shared_ptr<TSSLSocket> ssl(new TSSLSocket(ctx_, host, port, interruptListener));
   setup(ssl);
   return ssl;
 }
 
 
-void TSSLSocketFactory::setup(stdcxx::shared_ptr<TSSLSocket> ssl) {
+void TSSLSocketFactory::setup(std::shared_ptr<TSSLSocket> ssl) {
   ssl->server(server());
   if (access_ == NULL && !server()) {
-    access_ = stdcxx::shared_ptr<AccessManager>(new DefaultClientAccessManager);
+    access_ = std::shared_ptr<AccessManager>(new DefaultClientAccessManager);
   }
   if (access_ != NULL) {
     ssl->access(access_);
@@ -1005,20 +1032,28 @@
   }
   if (sslerrno) {
     errors += " (SSL_error_code = " + to_string(sslerrno) + ")";
+    if (sslerrno == SSL_ERROR_SYSCALL) {
+      char buf[4096];
+      int err;
+      while ((err = ERR_get_error()) != 0) {
+        errors += " ";
+        errors += ERR_error_string(err, buf);
+      }
+    }
   }
 }
 
 /**
  * Default implementation of AccessManager
  */
-Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) throw() {
+Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) noexcept {
   (void)sa;
   return SKIP;
 }
 
 Decision DefaultClientAccessManager::verify(const string& host,
                                             const char* name,
-                                            int size) throw() {
+                                            int size) noexcept {
   if (host.empty() || name == NULL || size <= 0) {
     return SKIP;
   }
@@ -1027,7 +1062,7 @@
 
 Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa,
                                             const char* data,
-                                            int size) throw() {
+                                            int size) noexcept {
   bool match = false;
   if (sa.ss_family == AF_INET && size == sizeof(in_addr)) {
     match = (memcmp(&((sockaddr_in*)&sa)->sin_addr, data, size) == 0);
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h
index 8527209..5a87d1e 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.h
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.h
@@ -26,7 +26,6 @@
 #include <openssl/ssl.h>
 #include <string>
 #include <thrift/concurrency/Mutex.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -78,6 +77,7 @@
   bool peek();
   void open();
   void close();
+  bool hasPendingDataToRead();
   uint32_t read(uint8_t* buf, uint32_t len);
   void write(const uint8_t* buf, uint32_t len);
   uint32_t write_partial(const uint8_t* buf, uint32_t len);
@@ -97,7 +97,7 @@
    *
    * @param manager  Instance of AccessManager
    */
-  virtual void access(stdcxx::shared_ptr<AccessManager> manager) { access_ = manager; }
+  virtual void access(std::shared_ptr<AccessManager> manager) { access_ = manager; }
   /**
    * Set eventSafe flag if libevent is used.
    */
@@ -111,37 +111,37 @@
   /**
    * Constructor.
    */
-  TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx);
+  TSSLSocket(std::shared_ptr<SSLContext> ctx);
   /**
    * Constructor with an interrupt signal.
    */
-  TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  TSSLSocket(std::shared_ptr<SSLContext> ctx, std::shared_ptr<THRIFT_SOCKET> interruptListener);
   /**
    * Constructor, create an instance of TSSLSocket given an existing socket.
    *
    * @param socket An existing socket
    */
-  TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket);
+  TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket);
   /**
    * Constructor, create an instance of TSSLSocket given an existing socket that can be interrupted.
    *
    * @param socket An existing socket
    */
-  TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener);
    /**
    * Constructor.
    *
    * @param host  Remote host name
    * @param port  Remote port number
    */
-  TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, std::string host, int port);
+  TSSLSocket(std::shared_ptr<SSLContext> ctx, std::string host, int port);
     /**
   * Constructor with an interrupt signal.
   *
   * @param host  Remote host name
   * @param port  Remote port number
   */
-    TSSLSocket(stdcxx::shared_ptr<SSLContext> ctx, std::string host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+    TSSLSocket(std::shared_ptr<SSLContext> ctx, std::string host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener);
   /**
    * Authorize peer access after SSL handshake completes.
    */
@@ -170,8 +170,8 @@
 
   bool server_;
   SSL* ssl_;
-  stdcxx::shared_ptr<SSLContext> ctx_;
-  stdcxx::shared_ptr<AccessManager> access_;
+  std::shared_ptr<SSLContext> ctx_;
+  std::shared_ptr<AccessManager> access_;
   friend class TSSLSocketFactory;
 
 private:
@@ -211,37 +211,37 @@
   /**
    * Create an instance of TSSLSocket with a fresh new socket.
    */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket();
+  virtual std::shared_ptr<TSSLSocket> createSocket();
   /**
    * Create an instance of TSSLSocket with a fresh new socket, which is interruptable.
    */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket(stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  virtual std::shared_ptr<TSSLSocket> createSocket(std::shared_ptr<THRIFT_SOCKET> interruptListener);
   /**
    * Create an instance of TSSLSocket with the given socket.
    *
    * @param socket An existing socket.
    */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket);
+  virtual std::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket);
   /**
    * Create an instance of TSSLSocket with the given socket which is interruptable.
    *
    * @param socket An existing socket.
    */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  virtual std::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener);
   /**
   * Create an instance of TSSLSocket.
   *
   * @param host  Remote host to be connected to
   * @param port  Remote port to be connected to
   */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port);
+  virtual std::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port);
   /**
   * Create an instance of TSSLSocket.
   *
   * @param host  Remote host to be connected to
   * @param port  Remote port to be connected to
   */
-  virtual stdcxx::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  virtual std::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener);
   /**
    * Set ciphers to be used in SSL handshake process.
    *
@@ -299,13 +299,13 @@
    *
    * @param manager  The AccessManager instance
    */
-  virtual void access(stdcxx::shared_ptr<AccessManager> manager) { access_ = manager; }
+  virtual void access(std::shared_ptr<AccessManager> manager) { access_ = manager; }
   static void setManualOpenSSLInitialization(bool manualOpenSSLInitialization) {
     manualOpenSSLInitialization_ = manualOpenSSLInitialization;
   }
 
 protected:
-  stdcxx::shared_ptr<SSLContext> ctx_;
+  std::shared_ptr<SSLContext> ctx_;
 
   /**
    * Override this method for custom password callback. It may be called
@@ -318,11 +318,11 @@
 
 private:
   bool server_;
-  stdcxx::shared_ptr<AccessManager> access_;
+  std::shared_ptr<AccessManager> access_;
   static concurrency::Mutex mutex_;
   static uint64_t count_;
   static bool manualOpenSSLInitialization_;
-  void setup(stdcxx::shared_ptr<TSSLSocket> ssl);
+  void setup(std::shared_ptr<TSSLSocket> ssl);
   static int passwordCallback(char* password, int size, int, void* data);
 };
 
@@ -334,7 +334,7 @@
   TSSLException(const std::string& message)
     : TTransportException(TTransportException::INTERNAL_ERROR, message) {}
 
-  virtual const char* what() const throw() {
+  virtual const char* what() const noexcept {
     if (message_.empty()) {
       return "TSSLException";
     } else {
@@ -385,7 +385,7 @@
    * @param  sa Peer IP address
    * @return True if the peer is trusted, false otherwise
    */
-  virtual Decision verify(const sockaddr_storage& /* sa */) throw() { return DENY; }
+  virtual Decision verify(const sockaddr_storage& /* sa */) noexcept { return DENY; }
   /**
    * Determine whether the peer should be granted access or not. It's called
    * every time a DNS subjectAltName/common name is extracted from peer's
@@ -401,7 +401,7 @@
    */
   virtual Decision verify(const std::string& /* host */,
                           const char* /* name */,
-                          int /* size */) throw() {
+                          int /* size */) noexcept {
     return DENY;
   }
   /**
@@ -415,7 +415,7 @@
    */
   virtual Decision verify(const sockaddr_storage& /* sa */,
                           const char* /* data */,
-                          int /* size */) throw() {
+                          int /* size */) noexcept {
     return DENY;
   }
 };
@@ -425,9 +425,9 @@
 class DefaultClientAccessManager : public AccessManager {
 public:
   // AccessManager interface
-  Decision verify(const sockaddr_storage& sa) throw();
-  Decision verify(const std::string& host, const char* name, int size) throw();
-  Decision verify(const sockaddr_storage& sa, const char* data, int size) throw();
+  Decision verify(const sockaddr_storage& sa) noexcept;
+  Decision verify(const std::string& host, const char* name, int size) noexcept;
+  Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp
index 3179b1a..118b993 100644
--- a/lib/cpp/src/thrift/transport/TServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp
@@ -46,7 +46,6 @@
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TServerSocket.h>
 #include <thrift/transport/PlatformSocket.h>
-#include <thrift/stdcxx.h>
 
 #ifndef AF_LOCAL
 #define AF_LOCAL AF_UNIX
@@ -81,7 +80,7 @@
 namespace thrift {
 namespace transport {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 TGetAddrInfoWrapper::TGetAddrInfoWrapper(const char* node,
                                          const char* service,
@@ -249,7 +248,7 @@
   } else {
     childInterruptSockWriter_ = sv[1];
     pChildInterruptSockReader_
-        = stdcxx::shared_ptr<THRIFT_SOCKET>(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets);
+        = std::shared_ptr<THRIFT_SOCKET>(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets);
   }
 
   // Validate port number
@@ -288,7 +287,7 @@
 
   if (!path_.empty()) {
     serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP);
-  } else {
+  } else if (res != NULL) {
     serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
   }
 
diff --git a/lib/cpp/src/thrift/transport/TServerSocket.h b/lib/cpp/src/thrift/transport/TServerSocket.h
index 1daaa82..b23d2c1 100644
--- a/lib/cpp/src/thrift/transport/TServerSocket.h
+++ b/lib/cpp/src/thrift/transport/TServerSocket.h
@@ -21,7 +21,6 @@
 #define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1
 
 #include <thrift/concurrency/Mutex.h>
-#include <thrift/stdcxx.h>
 #include <thrift/transport/PlatformSocket.h>
 #include <thrift/transport/TServerTransport.h>
 
@@ -62,7 +61,7 @@
  */
 class TServerSocket : public TServerTransport {
 public:
-  typedef apache::thrift::stdcxx::function<void(THRIFT_SOCKET fd)> socket_func_t;
+  typedef std::function<void(THRIFT_SOCKET fd)> socket_func_t;
 
   const static int DEFAULT_BACKLOG = 1024;
 
@@ -147,10 +146,10 @@
   void close();
 
 protected:
-  stdcxx::shared_ptr<TTransport> acceptImpl();
-  virtual stdcxx::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
+  std::shared_ptr<TTransport> acceptImpl();
+  virtual std::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
   bool interruptableChildren_;
-  stdcxx::shared_ptr<THRIFT_SOCKET> pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets
+  std::shared_ptr<THRIFT_SOCKET> pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets
 
 private:
   void notify(THRIFT_SOCKET notifySock);
diff --git a/lib/cpp/src/thrift/transport/TServerTransport.h b/lib/cpp/src/thrift/transport/TServerTransport.h
index 9d5a3d5..db7632a 100644
--- a/lib/cpp/src/thrift/transport/TServerTransport.h
+++ b/lib/cpp/src/thrift/transport/TServerTransport.h
@@ -22,7 +22,6 @@
 
 #include <thrift/transport/TTransport.h>
 #include <thrift/transport/TTransportException.h>
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -56,8 +55,8 @@
    * @return A new TTransport object
    * @throws TTransportException if there is an error
    */
-  stdcxx::shared_ptr<TTransport> accept() {
-    stdcxx::shared_ptr<TTransport> result = acceptImpl();
+  std::shared_ptr<TTransport> accept() {
+    std::shared_ptr<TTransport> result = acceptImpl();
     if (!result) {
       throw TTransportException("accept() may not return NULL");
     }
@@ -105,7 +104,7 @@
    * @return A newly allocated TTransport object
    * @throw TTransportException If an error occurs
    */
-  virtual stdcxx::shared_ptr<TTransport> acceptImpl() = 0;
+  virtual std::shared_ptr<TTransport> acceptImpl() = 0;
 };
 }
 }
diff --git a/lib/cpp/src/thrift/transport/TShortReadTransport.h b/lib/cpp/src/thrift/transport/TShortReadTransport.h
index 550b6ba..118252d 100644
--- a/lib/cpp/src/thrift/transport/TShortReadTransport.h
+++ b/lib/cpp/src/thrift/transport/TShortReadTransport.h
@@ -38,7 +38,7 @@
  */
 class TShortReadTransport : public TVirtualTransport<TShortReadTransport> {
 public:
-  TShortReadTransport(stdcxx::shared_ptr<TTransport> transport, double full_prob)
+  TShortReadTransport(std::shared_ptr<TTransport> transport, double full_prob)
     : transport_(transport), fullProb_(full_prob) {}
 
   bool isOpen() { return transport_->isOpen(); }
@@ -68,10 +68,10 @@
 
   void consume(uint32_t len) { return transport_->consume(len); }
 
-  stdcxx::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
+  std::shared_ptr<TTransport> getUnderlyingTransport() { return transport_; }
 
 protected:
-  stdcxx::shared_ptr<TTransport> transport_;
+  std::shared_ptr<TTransport> transport_;
   double fullProb_;
 };
 }
diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp
index d93d0ff..c6c2bfa 100644
--- a/lib/cpp/src/thrift/transport/TSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSocket.cpp
@@ -21,6 +21,9 @@
 
 #include <cstring>
 #include <sstream>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
@@ -141,7 +144,7 @@
 #endif
 }
 
-TSocket::TSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener)
+TSocket::TSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener)
   : port_(0),
     socket_(socket),
     peerPort_(0),
@@ -167,6 +170,26 @@
   close();
 }
 
+bool TSocket::hasPendingDataToRead() {
+  if (!isOpen()) {
+    return false;
+  }
+
+  int32_t retries = 0;
+  THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE numBytesAvailable;
+try_again:
+  int r = THRIFT_IOCTL_SOCKET(socket_, FIONREAD, &numBytesAvailable);
+  if (r == -1) {
+    int errno_copy = THRIFT_GET_SOCKET_ERROR;
+    if (errno_copy == THRIFT_EINTR && (retries++ < maxRecvRetries_)) {
+      goto try_again;
+    }
+    GlobalOutput.perror("TSocket::hasPendingDataToRead() THRIFT_IOCTL_SOCKET() " + getSocketInfo(), errno_copy);
+    throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy);
+  }
+  return numBytesAvailable > 0;
+}
+
 bool TSocket::isOpen() {
   return (socket_ != THRIFT_INVALID_SOCKET);
 }
@@ -786,11 +809,15 @@
 
 string TSocket::getSocketInfo() {
   std::ostringstream oss;
-  if (host_.empty() || port_ == 0) {
-    oss << "<Host: " << getPeerAddress();
-    oss << " Port: " << getPeerPort() << ">";
+  if (path_.empty()) {
+    if (host_.empty() || port_ == 0) {
+      oss << "<Host: " << getPeerAddress();
+      oss << " Port: " << getPeerPort() << ">";
+    } else {
+      oss << "<Host: " << host_ << " Port: " << port_ << ">";
+    }
   } else {
-    oss << "<Host: " << host_ << " Port: " << port_ << ">";
+    oss << "<Path: " << path_ << ">";
   }
   return oss.str();
 }
diff --git a/lib/cpp/src/thrift/transport/TSocket.h b/lib/cpp/src/thrift/transport/TSocket.h
index 1f95e68..4030d46 100644
--- a/lib/cpp/src/thrift/transport/TSocket.h
+++ b/lib/cpp/src/thrift/transport/TSocket.h
@@ -84,7 +84,9 @@
   virtual bool isOpen();
 
   /**
-   * Calls select on the socket to see if there is more data available.
+   * Checks whether there is more data available in the socket to read.
+   *
+   * This call blocks until at least one byte is available or the socket is closed.
    */
   virtual bool peek();
 
@@ -101,6 +103,17 @@
   virtual void close();
 
   /**
+   * Determines whether there is pending data to read or not.
+   *
+   * This call does not block.
+   * \throws TTransportException of types:
+   *           NOT_OPEN means the socket has been closed
+   *           UNKNOWN means something unexpected happened
+   * \returns true if there is pending data to read, false otherwise
+   */
+  virtual bool hasPendingDataToRead();
+
+  /**
    * Reads from the underlying socket.
    * \returns the number of bytes read or 0 indicates EOF
    * \throws TTransportException of types:
@@ -257,7 +270,7 @@
    * Constructor to create socket from file descriptor that
    * can be interrupted safely.
    */
-  TSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener);
+  TSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener);
 
   /**
    * Set a cache of the peer address (used when trivially available: e.g.
@@ -294,7 +307,7 @@
    * A shared socket pointer that will interrupt a blocking read if data
    * becomes available on it
    */
-  stdcxx::shared_ptr<THRIFT_SOCKET> interruptListener_;
+  std::shared_ptr<THRIFT_SOCKET> interruptListener_;
 
   /** Connect timeout in ms */
   int connTimeout_;
diff --git a/lib/cpp/src/thrift/transport/TSocketPool.cpp b/lib/cpp/src/thrift/transport/TSocketPool.cpp
index 963c69b..5477bbb 100644
--- a/lib/cpp/src/thrift/transport/TSocketPool.cpp
+++ b/lib/cpp/src/thrift/transport/TSocketPool.cpp
@@ -21,6 +21,9 @@
 
 #include <algorithm>
 #include <iostream>
+#if __cplusplus >= 201703L
+#include <random>
+#endif
 
 #include <thrift/transport/TSocketPool.h>
 
@@ -32,7 +35,7 @@
 namespace thrift {
 namespace transport {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 
 /**
  * TSocketPoolServer implementation
@@ -188,7 +191,13 @@
   }
 
   if (randomize_ && numServers > 1) {
-    random_shuffle(servers_.begin(), servers_.end());
+#if __cplusplus >= 201703L
+    std::random_device rng;
+    std::mt19937 urng(rng());
+    std::shuffle(servers_.begin(), servers_.end(), urng);
+#else
+    std::random_shuffle(servers_.begin(), servers_.end());
+#endif
   }
 
   for (size_t i = 0; i < numServers; ++i) {
@@ -217,7 +226,7 @@
       for (int j = 0; j < numRetries_; ++j) {
         try {
           TSocket::open();
-        } catch (TException e) {
+        } catch (const TException &e) {
           string errStr = "TSocketPool::open failed " + getSocketInfo() + ": " + e.what();
           GlobalOutput(errStr.c_str());
           socket_ = THRIFT_INVALID_SOCKET;
diff --git a/lib/cpp/src/thrift/transport/TSocketPool.h b/lib/cpp/src/thrift/transport/TSocketPool.h
index bd49e55..18f101c 100644
--- a/lib/cpp/src/thrift/transport/TSocketPool.h
+++ b/lib/cpp/src/thrift/transport/TSocketPool.h
@@ -92,7 +92,7 @@
    *
    * @param servers list of TSocketPoolServers
    */
-  TSocketPool(const std::vector<stdcxx::shared_ptr<TSocketPoolServer> >& servers);
+  TSocketPool(const std::vector<std::shared_ptr<TSocketPoolServer> >& servers);
 
   /**
    * Socket pool constructor
@@ -115,17 +115,17 @@
   /**
    * Add a server to the pool
    */
-  void addServer(stdcxx::shared_ptr<TSocketPoolServer>& server);
+  void addServer(std::shared_ptr<TSocketPoolServer>& server);
 
   /**
    * Set list of servers in this pool
    */
-  void setServers(const std::vector<stdcxx::shared_ptr<TSocketPoolServer> >& servers);
+  void setServers(const std::vector<std::shared_ptr<TSocketPoolServer> >& servers);
 
   /**
    * Get list of servers in this pool
    */
-  void getServers(std::vector<stdcxx::shared_ptr<TSocketPoolServer> >& servers);
+  void getServers(std::vector<std::shared_ptr<TSocketPoolServer> >& servers);
 
   /**
    * Sets how many times to keep retrying a host in the connect function.
@@ -163,13 +163,13 @@
   void close();
 
 protected:
-  void setCurrentServer(const stdcxx::shared_ptr<TSocketPoolServer>& server);
+  void setCurrentServer(const std::shared_ptr<TSocketPoolServer>& server);
 
   /** List of servers to connect to */
-  std::vector<stdcxx::shared_ptr<TSocketPoolServer> > servers_;
+  std::vector<std::shared_ptr<TSocketPoolServer> > servers_;
 
   /** Current server */
-  stdcxx::shared_ptr<TSocketPoolServer> currentServer_;
+  std::shared_ptr<TSocketPoolServer> currentServer_;
 
   /** How many times to retry each host in connect */
   int numRetries_;
diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h
index de03290..d844239 100644
--- a/lib/cpp/src/thrift/transport/TTransport.h
+++ b/lib/cpp/src/thrift/transport/TTransport.h
@@ -21,8 +21,8 @@
 #define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1
 
 #include <thrift/Thrift.h>
-#include <thrift/stdcxx.h>
 #include <thrift/transport/TTransportException.h>
+#include <memory>
 #include <string>
 
 namespace apache {
@@ -260,7 +260,7 @@
   /**
    * Default implementation does nothing, just returns the transport given.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
     return trans;
   }
 };
diff --git a/lib/cpp/src/thrift/transport/TTransportException.cpp b/lib/cpp/src/thrift/transport/TTransportException.cpp
index 9e15dbd..a527317 100644
--- a/lib/cpp/src/thrift/transport/TTransportException.cpp
+++ b/lib/cpp/src/thrift/transport/TTransportException.cpp
@@ -28,7 +28,7 @@
 namespace thrift {
 namespace transport {
 
-const char* TTransportException::what() const throw() {
+const char* TTransportException::what() const noexcept {
   if (message_.empty()) {
     switch (type_) {
     case UNKNOWN:
diff --git a/lib/cpp/src/thrift/transport/TTransportException.h b/lib/cpp/src/thrift/transport/TTransportException.h
index dbbb971..fb5f00c 100644
--- a/lib/cpp/src/thrift/transport/TTransportException.h
+++ b/lib/cpp/src/thrift/transport/TTransportException.h
@@ -65,7 +65,7 @@
   TTransportException(TTransportExceptionType type, const std::string& message, int errno_copy)
     : apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)), type_(type) {}
 
-  virtual ~TTransportException() throw() {}
+  virtual ~TTransportException() noexcept {}
 
   /**
    * Returns an error code that provides information about the type of error
@@ -73,9 +73,9 @@
    *
    * @return Error code
    */
-  TTransportExceptionType getType() const throw() { return type_; }
+  TTransportExceptionType getType() const noexcept { return type_; }
 
-  virtual const char* what() const throw();
+  virtual const char* what() const noexcept;
 
 protected:
   /** Just like strerror_r but returns a C++ string object. */
diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.cpp b/lib/cpp/src/thrift/transport/TTransportUtils.cpp
index 869b1fa..6f47c79 100644
--- a/lib/cpp/src/thrift/transport/TTransportUtils.cpp
+++ b/lib/cpp/src/thrift/transport/TTransportUtils.cpp
@@ -41,7 +41,11 @@
     // Double the size of the underlying buffer if it is full
     if (rLen_ == rBufSize_) {
       rBufSize_ *= 2;
-      rBuf_ = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_);
+      uint8_t *tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_);
+      if (tmpBuf == NULL) {
+       throw std::bad_alloc();
+      }
+      rBuf_ = tmpBuf;
     }
 
     // try to fill up the buffer
@@ -73,7 +77,12 @@
     while ((len + wLen_) >= newBufSize) {
       newBufSize *= 2;
     }
-    wBuf_ = (uint8_t*)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize);
+    uint8_t *tmpBuf= (uint8_t*)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize);
+    if (tmpBuf == NULL) {
+      throw std::bad_alloc();
+    }
+    wBuf_ = tmpBuf;
+
     wBufSize_ = newBufSize;
   }
 
@@ -94,8 +103,8 @@
 }
 
 TPipedFileReaderTransport::TPipedFileReaderTransport(
-    stdcxx::shared_ptr<TFileReaderTransport> srcTrans,
-    stdcxx::shared_ptr<TTransport> dstTrans)
+    std::shared_ptr<TFileReaderTransport> srcTrans,
+    std::shared_ptr<TTransport> dstTrans)
   : TPipedTransport(srcTrans, dstTrans), srcTrans_(srcTrans) {
 }
 
diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.h b/lib/cpp/src/thrift/transport/TTransportUtils.h
index 4e8ce26..4c82dd3 100644
--- a/lib/cpp/src/thrift/transport/TTransportUtils.h
+++ b/lib/cpp/src/thrift/transport/TTransportUtils.h
@@ -63,7 +63,7 @@
  */
 class TPipedTransport : virtual public TTransport {
 public:
-  TPipedTransport(stdcxx::shared_ptr<TTransport> srcTrans, stdcxx::shared_ptr<TTransport> dstTrans)
+  TPipedTransport(std::shared_ptr<TTransport> srcTrans, std::shared_ptr<TTransport> dstTrans)
     : srcTrans_(srcTrans),
       dstTrans_(dstTrans),
       rBufSize_(512),
@@ -86,8 +86,8 @@
     }
   }
 
-  TPipedTransport(stdcxx::shared_ptr<TTransport> srcTrans,
-                  stdcxx::shared_ptr<TTransport> dstTrans,
+  TPipedTransport(std::shared_ptr<TTransport> srcTrans,
+                  std::shared_ptr<TTransport> dstTrans,
                   uint32_t sz)
     : srcTrans_(srcTrans),
       dstTrans_(dstTrans),
@@ -119,7 +119,11 @@
       // Double the size of the underlying buffer if it is full
       if (rLen_ == rBufSize_) {
         rBufSize_ *= 2;
-        rBuf_ = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_);
+        uint8_t * tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_);
+	if (tmpBuf == NULL) {
+	  throw std::bad_alloc();
+	}
+	rBuf_ = tmpBuf;
       }
 
       // try to fill up the buffer
@@ -170,7 +174,7 @@
 
   void flush();
 
-  stdcxx::shared_ptr<TTransport> getTargetTransport() { return dstTrans_; }
+  std::shared_ptr<TTransport> getTargetTransport() { return dstTrans_; }
 
   /*
    * Override TTransport *_virt() functions to invoke our implementations.
@@ -181,8 +185,8 @@
   virtual void write_virt(const uint8_t* buf, uint32_t len) { this->write(buf, len); }
 
 protected:
-  stdcxx::shared_ptr<TTransport> srcTrans_;
-  stdcxx::shared_ptr<TTransport> dstTrans_;
+  std::shared_ptr<TTransport> srcTrans_;
+  std::shared_ptr<TTransport> dstTrans_;
 
   uint8_t* rBuf_;
   uint32_t rBufSize_;
@@ -204,7 +208,7 @@
 class TPipedTransportFactory : public TTransportFactory {
 public:
   TPipedTransportFactory() {}
-  TPipedTransportFactory(stdcxx::shared_ptr<TTransport> dstTrans) {
+  TPipedTransportFactory(std::shared_ptr<TTransport> dstTrans) {
     initializeTargetTransport(dstTrans);
   }
   virtual ~TPipedTransportFactory() {}
@@ -212,11 +216,11 @@
   /**
    * Wraps the base transport into a piped transport.
    */
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> srcTrans) {
-    return stdcxx::shared_ptr<TTransport>(new TPipedTransport(srcTrans, dstTrans_));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> srcTrans) {
+    return std::shared_ptr<TTransport>(new TPipedTransport(srcTrans, dstTrans_));
   }
 
-  virtual void initializeTargetTransport(stdcxx::shared_ptr<TTransport> dstTrans) {
+  virtual void initializeTargetTransport(std::shared_ptr<TTransport> dstTrans) {
     if (dstTrans_.get() == NULL) {
       dstTrans_ = dstTrans;
     } else {
@@ -225,7 +229,7 @@
   }
 
 protected:
-  stdcxx::shared_ptr<TTransport> dstTrans_;
+  std::shared_ptr<TTransport> dstTrans_;
 };
 
 /**
@@ -236,8 +240,8 @@
  */
 class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTransport {
 public:
-  TPipedFileReaderTransport(stdcxx::shared_ptr<TFileReaderTransport> srcTrans,
-                            stdcxx::shared_ptr<TTransport> dstTrans);
+  TPipedFileReaderTransport(std::shared_ptr<TFileReaderTransport> srcTrans,
+                            std::shared_ptr<TTransport> dstTrans);
 
   ~TPipedFileReaderTransport();
 
@@ -273,7 +277,7 @@
 protected:
   // shouldn't be used
   TPipedFileReaderTransport();
-  stdcxx::shared_ptr<TFileReaderTransport> srcTrans_;
+  std::shared_ptr<TFileReaderTransport> srcTrans_;
 };
 
 /**
@@ -283,23 +287,23 @@
 class TPipedFileReaderTransportFactory : public TPipedTransportFactory {
 public:
   TPipedFileReaderTransportFactory() {}
-  TPipedFileReaderTransportFactory(stdcxx::shared_ptr<TTransport> dstTrans)
+  TPipedFileReaderTransportFactory(std::shared_ptr<TTransport> dstTrans)
     : TPipedTransportFactory(dstTrans) {}
   virtual ~TPipedFileReaderTransportFactory() {}
 
-  stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> srcTrans) {
-    stdcxx::shared_ptr<TFileReaderTransport> pFileReaderTransport
-        = stdcxx::dynamic_pointer_cast<TFileReaderTransport>(srcTrans);
+  std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> srcTrans) {
+    std::shared_ptr<TFileReaderTransport> pFileReaderTransport
+        = std::dynamic_pointer_cast<TFileReaderTransport>(srcTrans);
     if (pFileReaderTransport.get() != NULL) {
       return getFileReaderTransport(pFileReaderTransport);
     } else {
-      return stdcxx::shared_ptr<TTransport>();
+      return std::shared_ptr<TTransport>();
     }
   }
 
-  stdcxx::shared_ptr<TFileReaderTransport> getFileReaderTransport(
-      stdcxx::shared_ptr<TFileReaderTransport> srcTrans) {
-    return stdcxx::shared_ptr<TFileReaderTransport>(
+  std::shared_ptr<TFileReaderTransport> getFileReaderTransport(
+      std::shared_ptr<TFileReaderTransport> srcTrans) {
+    return std::shared_ptr<TFileReaderTransport>(
         new TPipedFileReaderTransport(srcTrans, dstTrans_));
   }
 };
diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.cpp b/lib/cpp/src/thrift/transport/TZlibTransport.cpp
index fb5cc5d..e426dc3 100644
--- a/lib/cpp/src/thrift/transport/TZlibTransport.cpp
+++ b/lib/cpp/src/thrift/transport/TZlibTransport.cpp
@@ -255,6 +255,15 @@
     throw TTransportException(TTransportException::BAD_ARGS, "flush() called after finish()");
   }
 
+  flushToZlib(uwbuf_, uwpos_, Z_BLOCK);
+  uwpos_ = 0;
+
+  if(wstream_->avail_out < 6){
+    transport_->write(cwbuf_, cwbuf_size_ - wstream_->avail_out);
+    wstream_->next_out = cwbuf_;
+    wstream_->avail_out = cwbuf_size_;
+  }
+
   flushToTransport(Z_FULL_FLUSH);
 }
 
@@ -285,7 +294,7 @@
   wstream_->avail_in = len;
 
   while (true) {
-    if (flush == Z_NO_FLUSH && wstream_->avail_in == 0) {
+    if ((flush == Z_NO_FLUSH || flush == Z_BLOCK) && wstream_->avail_in == 0) {
       break;
     }
 
diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h
index a0fb464..b45ec43 100644
--- a/lib/cpp/src/thrift/transport/TZlibTransport.h
+++ b/lib/cpp/src/thrift/transport/TZlibTransport.h
@@ -38,7 +38,7 @@
       zlib_status_(status),
       zlib_msg_(msg == NULL ? "(null)" : msg) {}
 
-  virtual ~TZlibTransportException() throw() {}
+  virtual ~TZlibTransportException() noexcept {}
 
   int getZlibStatus() { return zlib_status_; }
   std::string getZlibMessage() { return zlib_msg_; }
@@ -78,7 +78,7 @@
    * @param cwbuf_size   Compressed buffer size for writing.
    * @param comp_level   Compression level (0=none[fast], 6=default, 9=max[slow]).
    */
-  TZlibTransport(stdcxx::shared_ptr<TTransport> transport,
+  TZlibTransport(std::shared_ptr<TTransport> transport,
                  int urbuf_size = DEFAULT_URBUF_SIZE,
                  int crbuf_size = DEFAULT_CRBUF_SIZE,
                  int uwbuf_size = DEFAULT_UWBUF_SIZE,
@@ -180,7 +180,7 @@
   static const int DEFAULT_UWBUF_SIZE = 128;
   static const int DEFAULT_CWBUF_SIZE = 1024;
 
-  stdcxx::shared_ptr<TTransport> getUnderlyingTransport() const { return transport_; }
+  std::shared_ptr<TTransport> getUnderlyingTransport() const { return transport_; }
 
 protected:
   inline void checkZlibRv(int status, const char* msg);
@@ -195,7 +195,7 @@
   // Larger (or equal) writes are dumped straight to zlib.
   static const uint32_t MIN_DIRECT_DEFLATE_SIZE = 32;
 
-  stdcxx::shared_ptr<TTransport> transport_;
+  std::shared_ptr<TTransport> transport_;
 
   int urpos_;
   int uwpos_;
@@ -231,8 +231,8 @@
 
   virtual ~TZlibTransportFactory() {}
 
-  virtual stdcxx::shared_ptr<TTransport> getTransport(stdcxx::shared_ptr<TTransport> trans) {
-    return stdcxx::shared_ptr<TTransport>(new TZlibTransport(trans));
+  virtual std::shared_ptr<TTransport> getTransport(std::shared_ptr<TTransport> trans) {
+    return std::shared_ptr<TTransport>(new TZlibTransport(trans));
   }
 };
 }
diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp
index 2e0ccf5..d2683b0 100644
--- a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp
+++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp
@@ -28,13 +28,7 @@
 namespace transport {
 
 TWinsockSingleton::instance_ptr TWinsockSingleton::instance_ptr_(NULL);
-#if USE_BOOST_THREAD
-boost::once_flag TWinsockSingleton::flags_ = BOOST_ONCE_INIT;
-#elif USE_STD_THREAD
 std::once_flag TWinsockSingleton::flags_;
-#else
-#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD
-#endif
 
 //------------------------------------------------------------------------------
 TWinsockSingleton::TWinsockSingleton(void) {
@@ -55,11 +49,7 @@
 
 //------------------------------------------------------------------------------
 void TWinsockSingleton::create(void) {
-#if USE_BOOST_THREAD
-  boost::call_once(init, flags_);
-#elif USE_STD_THREAD
   std::call_once(flags_, init);
-#endif
 }
 
 //------------------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.h b/lib/cpp/src/thrift/windows/TWinsockSingleton.h
index 0eab6d4..a30806b 100644
--- a/lib/cpp/src/thrift/windows/TWinsockSingleton.h
+++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.h
@@ -33,15 +33,9 @@
 // boost
 #include <boost/noncopyable.hpp>
 
-#if USE_BOOST_THREAD
-#include <boost/thread/once.hpp>
-#elif USE_STD_THREAD
+#include <memory>
 #include <mutex>
-#else
-#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD
-#endif
 
-#include <thrift/stdcxx.h>
 
 namespace apache {
 namespace thrift {
@@ -54,7 +48,7 @@
 class TWinsockSingleton : private boost::noncopyable {
 
 public:
-  typedef stdcxx::shared_ptr<TWinsockSingleton> instance_ptr;
+  typedef std::shared_ptr<TWinsockSingleton> instance_ptr;
 
 private:
   TWinsockSingleton(void);
@@ -70,13 +64,7 @@
 
 private:
   static instance_ptr instance_ptr_;
-#if USE_BOOST_THREAD
-  static boost::once_flag flags_;
-#elif USE_STD_THREAD
   static std::once_flag flags_;
-#else
-#error Need a non-Boost non-C++11 way to track single initialization here.
-#endif
 };
 }
 }
diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h
index a361eac..a5f4457 100644
--- a/lib/cpp/src/thrift/windows/config.h
+++ b/lib/cpp/src/thrift/windows/config.h
@@ -31,9 +31,6 @@
 // use std::thread in MSVC11 (2012) or newer and in MinGW
 #if (_MSC_VER >= 1700) || defined(__MINGW32__)
 #define USE_STD_THREAD 1
-#else
-// otherwise use boost threads
-#define USE_BOOST_THREAD 1
 #endif
 
 // Something that defines PRId64 is required to build
@@ -70,7 +67,6 @@
 #pragma warning(disable : 4996) // Deprecated posix name.
 #endif
 
-#define VERSION "0.11.0"
 #define HAVE_GETTIMEOFDAY 1
 #define HAVE_SYS_STAT_H 1
 
diff --git a/lib/cpp/test/AllProtocolTests.tcc b/lib/cpp/test/AllProtocolTests.tcc
index b6df656..a7eab07 100644
--- a/lib/cpp/test/AllProtocolTests.tcc
+++ b/lib/cpp/test/AllProtocolTests.tcc
@@ -28,7 +28,7 @@
 
 #include "GenericHelpers.h"
 
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 using namespace apache::thrift;
 using namespace apache::thrift::protocol;
 using namespace apache::thrift::transport;
diff --git a/lib/cpp/test/Benchmark.cpp b/lib/cpp/test/Benchmark.cpp
index afde7d4..5ff77aa 100644
--- a/lib/cpp/test/Benchmark.cpp
+++ b/lib/cpp/test/Benchmark.cpp
@@ -23,8 +23,8 @@
 #include <iostream>
 #define _USE_MATH_DEFINES
 #include <math.h>
+#include <memory>
 #include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/stdcxx.h"
 #include "thrift/transport/TBufferTransports.h"
 #include "gen-cpp/DebugProtoTest_types.h"
 
@@ -68,7 +68,7 @@
   ooe.base64 = "\1\2\3\255";
 
   int num = 100000;
-  apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer(num*1000));
+  std::shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer(num*1000));
 
   uint8_t* data = NULL;
   uint32_t datasize = 0;
@@ -89,7 +89,7 @@
   buf->getBuffer(&data, &datasize);
 
   {
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer> prot(buf2);
     OneOfEach ooe2;
     double elapsed = 0.0;
@@ -117,7 +117,7 @@
 
   {
     OneOfEach ooe2;
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
     double elapsed = 0.0;
     Timer timer;
@@ -143,7 +143,7 @@
   }
 
   {
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer> prot(buf2);
     OneOfEach ooe2;
     double elapsed = 0.0;
@@ -182,7 +182,7 @@
   buf->getBuffer(&data, &datasize);
 
   {
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer> prot(buf2);
     ListDoublePerf listDoublePerf2;
     double elapsed = 0.0;
@@ -206,7 +206,7 @@
 
   {
     ListDoublePerf listDoublePerf2;
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
     double elapsed = 0.0;
     Timer timer;
@@ -228,7 +228,7 @@
   }
 
   {
-    apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
+    std::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
     TBinaryProtocolT<TMemoryBuffer> prot(buf2);
     ListDoublePerf listDoublePerf2;
     double elapsed = 0.0;
diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt
index 5c5ed18..82d47a6 100644
--- a/lib/cpp/test/CMakeLists.txt
+++ b/lib/cpp/test/CMakeLists.txt
@@ -1,4 +1,4 @@
-#
+#
 # 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
@@ -19,9 +19,6 @@
 
 include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
 
-add_definitions("-D__STDC_FORMAT_MACROS")
-add_definitions("-D__STDC_LIMIT_MACROS")
-
 if (WITH_DYN_LINK_TEST)
     add_definitions( -DBOOST_TEST_DYN_LINK )
 endif()
@@ -43,6 +40,10 @@
     gen-cpp/Recursive_types.h
     gen-cpp/ThriftTest_types.cpp
     gen-cpp/ThriftTest_types.h
+    gen-cpp/OneWayTest_types.cpp
+    gen-cpp/OneWayTest_types.h
+    gen-cpp/OneWayService.cpp
+    gen-cpp/OneWayService.h
     gen-cpp/TypedefTest_types.cpp
     gen-cpp/TypedefTest_types.h
     ThriftTest_extras.cpp
@@ -71,6 +72,7 @@
 
 set(UnitTest_SOURCES
     UnitTestMain.cpp
+    OneWayHTTPTest.cpp
     TMemoryBufferTest.cpp
     TBufferBaseTest.cpp
     Base64Test.cpp
@@ -80,7 +82,7 @@
     TServerTransportTest.cpp
 )
 
-if(NOT WITH_BOOSTTHREADS AND NOT WITH_STDTHREADS AND NOT MSVC AND NOT MINGW)
+if(NOT WITH_STDTHREADS AND NOT MSVC AND NOT MINGW)
     list(APPEND UnitTest_SOURCES concurrency/MutexTest.cpp)
     list(APPEND UnitTest_SOURCES concurrency/RWMutexStarveTest.cpp)
 endif()
@@ -394,6 +396,10 @@
     COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift
 )
 
+add_custom_command(OUTPUT gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_constants.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h gen-cpp/OneWayTest_constants.h gen-cpp/OneWayTest_types.cpp
+    COMMAND ${THRIFT_COMPILER} --gen cpp ${CMAKE_CURRENT_SOURCE_DIR}/OneWayTest.thrift
+)
+
 add_custom_command(OUTPUT gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h
     COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style ${CMAKE_CURRENT_SOURCE_DIR}/processor/proc.thrift
 )
diff --git a/lib/cpp/test/DebugProtoTest.cpp b/lib/cpp/test/DebugProtoTest.cpp
index e04600a..060f354 100644
--- a/lib/cpp/test/DebugProtoTest.cpp
+++ b/lib/cpp/test/DebugProtoTest.cpp
@@ -21,14 +21,14 @@
 #include <cmath>
 #include "gen-cpp/DebugProtoTest_types.h"
 #include <thrift/protocol/TDebugProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #define BOOST_TEST_MODULE DebugProtoTest
 #include <boost/test/unit_test.hpp>
 
 using namespace thrift::test::debug;
 
-static ::apache::thrift::stdcxx::shared_ptr<OneOfEach> ooe;
+static ::std::shared_ptr<OneOfEach> ooe;
 
 void testCaseSetup_1() {
   ooe.reset(new OneOfEach);
@@ -81,7 +81,7 @@
     "Expected:\n" << expected_result << "\nGotten:\n" << result);
 }
 
-static ::apache::thrift::stdcxx::shared_ptr<Nesting> n;
+static ::std::shared_ptr<Nesting> n;
 
 void testCaseSetup_2() {
   testCaseSetup_1();
@@ -149,7 +149,7 @@
     "Expected:\n" << expected_result << "\nGotten:\n" << result);
 }
 
-static ::apache::thrift::stdcxx::shared_ptr<HolyMoley> hm;
+static ::std::shared_ptr<HolyMoley> hm;
 
 void testCaseSetup_3() {
   testCaseSetup_2();
diff --git a/lib/cpp/test/GenericHelpers.h b/lib/cpp/test/GenericHelpers.h
index e131c42..bcef9f2 100644
--- a/lib/cpp/test/GenericHelpers.h
+++ b/lib/cpp/test/GenericHelpers.h
@@ -21,7 +21,7 @@
 #define _THRIFT_TEST_GENERICHELPERS_H_ 1
 
 #include <thrift/protocol/TProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/Thrift.h>
 
 /* ClassName Helper for cleaner exceptions */
@@ -63,43 +63,43 @@
 public:
   /* Write functions */
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int8_t& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int8_t& val) {
     return proto->writeByte(val);
   }
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int16_t& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int16_t& val) {
     return proto->writeI16(val);
   }
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int32_t& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int32_t& val) {
     return proto->writeI32(val);
   }
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const double& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const double& val) {
     return proto->writeDouble(val);
   }
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int64_t& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const int64_t& val) {
     return proto->writeI64(val);
   }
 
-  static uint32_t write(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, const std::string& val) {
+  static uint32_t write(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, const std::string& val) {
     return proto->writeString(val);
   }
 
   /* Read functions */
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, int8_t& val) { return proto->readByte(val); }
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, int8_t& val) { return proto->readByte(val); }
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, int16_t& val) { return proto->readI16(val); }
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, int16_t& val) { return proto->readI16(val); }
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, int32_t& val) { return proto->readI32(val); }
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, int32_t& val) { return proto->readI32(val); }
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, int64_t& val) { return proto->readI64(val); }
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, int64_t& val) { return proto->readI64(val); }
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, double& val) { return proto->readDouble(val); }
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, double& val) { return proto->readDouble(val); }
 
-  static uint32_t read(apache::thrift::stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> proto, std::string& val) {
+  static uint32_t read(std::shared_ptr<apache::thrift::protocol::TProtocol> proto, std::string& val) {
     return proto->readString(val);
   }
 };
diff --git a/lib/cpp/test/JSONProtoTest.cpp b/lib/cpp/test/JSONProtoTest.cpp
index 77bc250..c2ad73e 100644
--- a/lib/cpp/test/JSONProtoTest.cpp
+++ b/lib/cpp/test/JSONProtoTest.cpp
@@ -22,7 +22,7 @@
 #include <iomanip>
 #include <sstream>
 #include <thrift/protocol/TJSONProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TBufferTransports.h>
 #include "gen-cpp/DebugProtoTest_types.h"
 
@@ -34,7 +34,7 @@
 using apache::thrift::transport::TMemoryBuffer;
 using apache::thrift::protocol::TJSONProtocol;
 
-static stdcxx::shared_ptr<OneOfEach> ooe;
+static std::shared_ptr<OneOfEach> ooe;
 
 void testCaseSetup_1() {
   ooe.reset(new OneOfEach);
@@ -67,7 +67,7 @@
     "Expected:\n" << expected_result << "\nGotten:\n" << result);
 }
 
-static stdcxx::shared_ptr<Nesting> n;
+static std::shared_ptr<Nesting> n;
 
 void testCaseSetup_2() {
   testCaseSetup_1();
@@ -107,7 +107,7 @@
     "Expected:\n" << expected_result << "\nGotten:\n" << result);
 }
 
-static stdcxx::shared_ptr<HolyMoley> hm;
+static std::shared_ptr<HolyMoley> hm;
 
 void testCaseSetup_3() {
   testCaseSetup_2();
@@ -185,8 +185,8 @@
 BOOST_AUTO_TEST_CASE(test_json_proto_4) {
   testCaseSetup_1();
 
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   ooe->write(proto.get());
   OneOfEach ooe2;
@@ -198,8 +198,8 @@
 BOOST_AUTO_TEST_CASE(test_json_proto_5) {
   testCaseSetup_3();
 
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   hm->write(proto.get());
   HolyMoley hm2;
@@ -236,8 +236,8 @@
 }
 
 BOOST_AUTO_TEST_CASE(test_json_proto_7) {
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   Base64 base;
   base.a = 123;
@@ -265,9 +265,9 @@
   "\",3,1,2,3]}}";
 
   const std::size_t bufSiz = strlen(json_string) * sizeof(char);
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
     (uint8_t*)(json_string), static_cast<uint32_t>(bufSiz)));
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   OneOfEach ooe2;
 
@@ -294,9 +294,9 @@
   "\",3,1,2,3]}}";
   const char* expected_zomg_unicode = "\xe0\xb8\x81 \xf0\x9d\x94\xbe";
 
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
     (uint8_t*)(json_string), sizeof(json_string)));
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   OneOfEach ooe2;
   ooe2.read(proto.get());
@@ -315,9 +315,9 @@
   ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
   "\",3,1,2,3]}}";
 
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
     (uint8_t*)(json_string), sizeof(json_string)));
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   OneOfEach ooe2;
   BOOST_CHECK_THROW(ooe2.read(proto.get()),
@@ -333,9 +333,9 @@
   ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
   "\",3,1,2,3]}}";
 
-  stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
     (uint8_t*)(json_string), sizeof(json_string)));
-  stdcxx::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+  std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
 
   OneOfEach ooe2;
   BOOST_CHECK_THROW(ooe2.read(proto.get()),
diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am
index c298e26..d645a65 100755
--- a/lib/cpp/test/Makefile.am
+++ b/lib/cpp/test/Makefile.am
@@ -28,6 +28,9 @@
                 gen-cpp/ChildService.h \
                 gen-cpp/EmptyService.h \
                 gen-cpp/ParentService.h \
+		gen-cpp/OneWayTest_types.h \
+		gen-cpp/OneWayService.h \
+		gen-cpp/OneWayTest_constants.h \
                 gen-cpp/proc_types.h
 
 noinst_LTLIBRARIES = libtestgencpp.la libprocessortest.la
@@ -36,6 +39,8 @@
 	gen-cpp/AnnotationTest_types.h \
 	gen-cpp/DebugProtoTest_types.cpp \
 	gen-cpp/DebugProtoTest_types.h \
+	gen-cpp/DoubleConstantsTest_constants.cpp \
+	gen-cpp/DoubleConstantsTest_constants.h \
 	gen-cpp/EnumTest_types.cpp \
 	gen-cpp/EnumTest_types.h \
 	gen-cpp/OptionalRequiredTest_types.cpp \
@@ -48,6 +53,12 @@
 	gen-cpp/ThriftTest_constants.h \
 	gen-cpp/TypedefTest_types.cpp \
 	gen-cpp/TypedefTest_types.h \
+	gen-cpp/OneWayService.cpp \
+	gen-cpp/OneWayTest_constants.cpp \
+	gen-cpp/OneWayTest_types.h \
+	gen-cpp/OneWayService.h \
+	gen-cpp/OneWayTest_constants.h \
+	gen-cpp/OneWayTest_types.cpp \
 	ThriftTest_extras.cpp \
 	DebugProtoTest_extras.cpp
 
@@ -93,6 +104,7 @@
 	link_test \
 	OpenSSLManualInitTest \
 	EnumTest \
+	RenderedDoubleConstantsTest \
         AnnotationTest
 
 if AMX_HAVE_LIBEVENT
@@ -113,6 +125,7 @@
 
 UnitTests_SOURCES = \
 	UnitTestMain.cpp \
+	OneWayHTTPTest.cpp \
 	TMemoryBufferTest.cpp \
 	TBufferBaseTest.cpp \
 	Base64Test.cpp \
@@ -122,15 +135,15 @@
 	TServerTransportTest.cpp \
 	TTransportCheckThrow.h
 
-if !WITH_BOOSTTHREADS
 UnitTests_SOURCES += \
   concurrency/MutexTest.cpp \
   concurrency/RWMutexStarveTest.cpp
-endif
 
 UnitTests_LDADD = \
   libtestgencpp.la \
-  $(BOOST_TEST_LDADD)
+  $(BOOST_TEST_LDADD) \
+  $(BOOST_SYSTEM_LDADD) \
+  $(BOOST_THREAD_LDADD)
 
 TInterruptTest_SOURCES = \
 	TSocketInterruptTest.cpp \
@@ -190,6 +203,10 @@
   libtestgencpp.la \
   $(BOOST_TEST_LDADD)
 
+RenderedDoubleConstantsTest_SOURCES = RenderedDoubleConstantsTest.cpp
+
+RenderedDoubleConstantsTest_LDADD = libtestgencpp.la $(BOOST_TEST_LDADD)
+
 AnnotationTest_SOURCES = \
 	AnnotationTest.cpp
 
@@ -367,6 +384,10 @@
 gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h: $(top_srcdir)/test/DebugProtoTest.thrift
 	$(THRIFT) --gen cpp $<
 
+gen-cpp/DoubleConstantsTest_constants.cpp gen-cpp/DoubleConstantsTest_constants.h: $(top_srcdir)/test/DoubleConstantsTest.thrift
+	$(THRIFT) --gen cpp $<
+
+
 gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h: $(top_srcdir)/test/EnumTest.thrift
 	$(THRIFT) --gen cpp $<
 
@@ -385,6 +406,9 @@
 gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h: $(top_srcdir)/test/ThriftTest.thrift
 	$(THRIFT) --gen cpp $<
 
+gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_constants.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h gen-cpp/OneWayTest_constants.h gen-cpp/OneWayTest_types.cpp: OneWayTest.thrift
+	$(THRIFT) --gen cpp $<
+
 gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift
 	$(THRIFT) --gen cpp:templates,cob_style $<
 
@@ -401,4 +425,5 @@
 	qt \
 	CMakeLists.txt \
 	DebugProtoTest_extras.cpp \
-	ThriftTest_extras.cpp
+	ThriftTest_extras.cpp \
+	OneWayTest.thrift
diff --git a/lib/cpp/test/OneWayHTTPTest.cpp b/lib/cpp/test/OneWayHTTPTest.cpp
new file mode 100644
index 0000000..89fa164
--- /dev/null
+++ b/lib/cpp/test/OneWayHTTPTest.cpp
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/thread.hpp>
+#include <iostream>
+#include <climits>
+#include <vector>
+#include <thrift/concurrency/Monitor.h>
+#include <thrift/protocol/TBinaryProtocol.h>
+#include <thrift/protocol/TJSONProtocol.h>
+#include <thrift/server/TThreadedServer.h>
+#include <thrift/transport/THttpServer.h>
+#include <thrift/transport/THttpClient.h>
+#include <thrift/transport/TServerSocket.h>
+#include <thrift/transport/TSocket.h>
+#include <memory>
+#include <thrift/transport/TBufferTransports.h>
+#include "gen-cpp/OneWayService.h"
+
+BOOST_AUTO_TEST_SUITE(OneWayHTTPTest)
+
+using namespace apache::thrift;
+using apache::thrift::protocol::TProtocol;
+using apache::thrift::protocol::TBinaryProtocol;
+using apache::thrift::protocol::TBinaryProtocolFactory;
+using apache::thrift::protocol::TJSONProtocol;
+using apache::thrift::protocol::TJSONProtocolFactory;
+using apache::thrift::server::TThreadedServer;
+using apache::thrift::server::TServerEventHandler;
+using apache::thrift::transport::TTransport;
+using apache::thrift::transport::THttpServer;
+using apache::thrift::transport::THttpServerTransportFactory;
+using apache::thrift::transport::THttpClient;
+using apache::thrift::transport::TBufferedTransport;
+using apache::thrift::transport::TBufferedTransportFactory;
+using apache::thrift::transport::TMemoryBuffer;
+using apache::thrift::transport::TServerSocket;
+using apache::thrift::transport::TSocket;
+using apache::thrift::transport::TTransportException;
+using std::shared_ptr;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+namespace utf = boost::unit_test;
+
+// Define this env var to enable some logging (in case you need to debug)
+#undef ENABLE_STDERR_LOGGING
+
+class OneWayServiceHandler : public onewaytest::OneWayServiceIf {
+public:
+  OneWayServiceHandler() {}
+
+  void roundTripRPC() override {
+#ifdef ENABLE_STDERR_LOGGING
+    cerr << "roundTripRPC()" << endl;
+#endif
+  }
+  void oneWayRPC() {
+#ifdef ENABLE_STDERR_LOGGING
+    cerr << "oneWayRPC()" << std::endl ;
+#endif
+ }
+};
+
+class OneWayServiceCloneFactory : virtual public onewaytest::OneWayServiceIfFactory {
+ public:
+  virtual ~OneWayServiceCloneFactory() {}
+  virtual onewaytest::OneWayServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo)
+  {
+    (void)connInfo ;
+    return new OneWayServiceHandler;
+  }
+  virtual void releaseHandler( onewaytest::OneWayServiceIf* handler) {
+    delete handler;
+  }
+};
+
+class RPC0ThreadClass {
+public:
+  RPC0ThreadClass(TThreadedServer& server) : server_(server) { } // Constructor
+~RPC0ThreadClass() { } // Destructor
+
+void Run() {
+  server_.serve() ;
+}
+ TThreadedServer& server_ ;
+} ;
+
+using apache::thrift::concurrency::Monitor;
+using apache::thrift::concurrency::Mutex;
+using apache::thrift::concurrency::Synchronized;
+
+// copied from IntegrationTest
+class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
+public:
+  TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
+  virtual ~TServerReadyEventHandler() {}
+  virtual void preServe() {
+    Synchronized sync(*this);
+    isListening_ = true;
+    notify();
+  }
+  virtual void* createContext(shared_ptr<TProtocol> input,
+                              shared_ptr<TProtocol> output) {
+    Synchronized sync(*this);
+    ++accepted_;
+    notify();
+
+    (void)input;
+    (void)output;
+    return NULL;
+  }
+  bool isListening() const { return isListening_; }
+  uint64_t acceptedCount() const { return accepted_; }
+
+private:
+  bool isListening_;
+  uint64_t accepted_;
+};
+
+class TBlockableBufferedTransport : public TBufferedTransport {
+ public:
+  TBlockableBufferedTransport(std::shared_ptr<TTransport> transport)
+    : TBufferedTransport(transport, 10240),
+    blocked_(false) {
+  }
+
+  uint32_t write_buffer_length() {
+    uint32_t have_bytes = static_cast<uint32_t>(wBase_ - wBuf_.get());
+    return have_bytes ;
+  }
+
+  void block() {
+    blocked_ = true ;
+#ifdef ENABLE_STDERR_LOGGING
+    cerr << "block flushing\n" ;
+#endif
+ }
+  void unblock() {
+    blocked_ = false ;
+#ifdef ENABLE_STDERR_LOGGING
+    cerr << "unblock flushing, buffer is\n<<" << std::string((char *)wBuf_.get(), write_buffer_length()) << ">>\n" ;
+#endif
+ }
+
+  void flush() override {
+    if (blocked_) {
+#ifdef ENABLE_STDERR_LOGGING
+      cerr << "flush was blocked\n" ;
+#endif
+      return ;
+    }
+    TBufferedTransport::flush() ;
+  }
+
+  bool blocked_ ;
+} ;
+
+BOOST_AUTO_TEST_CASE( JSON_BufferedHTTP )
+{
+  std::shared_ptr<TServerSocket> ss = std::make_shared<TServerSocket>(0) ;
+  TThreadedServer server(
+    std::make_shared<onewaytest::OneWayServiceProcessorFactory>(std::make_shared<OneWayServiceCloneFactory>()),
+    ss, //port
+    std::make_shared<THttpServerTransportFactory>(),
+    std::make_shared<TJSONProtocolFactory>());
+
+  std::shared_ptr<TServerReadyEventHandler> pEventHandler(new TServerReadyEventHandler) ;
+  server.setServerEventHandler(pEventHandler);
+
+#ifdef ENABLE_STDERR_LOGGING
+  cerr << "Starting the server...\n";
+#endif
+  RPC0ThreadClass t(server) ;
+  boost::thread thread(&RPC0ThreadClass::Run, &t);
+
+  {
+    Synchronized sync(*(pEventHandler.get()));
+    while (!pEventHandler->isListening()) {
+      pEventHandler->wait();
+    }
+  }
+
+  int port = ss->getPort() ;
+#ifdef ENABLE_STDERR_LOGGING
+  cerr << "port " << port << endl ;
+#endif
+
+  {
+    std::shared_ptr<TSocket> socket(new TSocket("localhost", port));
+    socket->setRecvTimeout(10000) ; // 1000msec should be enough
+    std::shared_ptr<TBlockableBufferedTransport> blockable_transport(new TBlockableBufferedTransport(socket));
+    std::shared_ptr<TTransport> transport(new THttpClient(blockable_transport, "localhost", "/service"));
+    std::shared_ptr<TProtocol> protocol(new TJSONProtocol(transport));
+    onewaytest::OneWayServiceClient client(protocol);
+
+
+    transport->open();
+    client.roundTripRPC();
+    blockable_transport->block() ;
+    uint32_t size0 = blockable_transport->write_buffer_length() ;
+    client.send_oneWayRPC() ;
+    uint32_t size1 = blockable_transport->write_buffer_length() ;
+    client.send_oneWayRPC() ;
+    uint32_t size2 = blockable_transport->write_buffer_length() ;
+    BOOST_CHECK((size1 - size0) == (size2 - size1)) ;
+    blockable_transport->unblock() ;
+    client.send_roundTripRPC() ;
+    blockable_transport->flush() ;
+    try {
+      client.recv_roundTripRPC() ;
+    } catch (TTransportException e) {
+      BOOST_ERROR( "we should not get a transport exception -- this means we failed: " + std::string(e.what()) ) ;
+    }
+    transport->close();
+  }
+  server.stop();
+  thread.join() ;
+#ifdef ENABLE_STDERR_LOGGING
+  cerr << "finished.\n";
+#endif
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/lib/cpp/test/OneWayTest.thrift b/lib/cpp/test/OneWayTest.thrift
new file mode 100644
index 0000000..127e9ff
--- /dev/null
+++ b/lib/cpp/test/OneWayTest.thrift
@@ -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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+namespace c_glib OneWayTest
+namespace java onewaytest
+namespace cpp onewaytest
+namespace rb Onewaytest
+namespace perl OneWayTest
+namespace csharp Onewaytest
+namespace js OneWayTest
+namespace st OneWayTest
+namespace py OneWayTest
+namespace py.twisted OneWayTest
+namespace go onewaytest
+namespace php OneWayTest
+namespace delphi Onewaytest
+namespace cocoa OneWayTest
+namespace lua OneWayTest
+namespace xsd test (uri = 'http://thrift.apache.org/ns/OneWayTest')
+namespace netcore ThriftAsync.OneWayTest
+
+// a minimal Thrift service, for use in OneWayHTTPTtest.cpp
+service OneWayService {
+  void roundTripRPC(),
+  oneway void oneWayRPC()
+}
diff --git a/lib/cpp/test/OptionalRequiredTest.cpp b/lib/cpp/test/OptionalRequiredTest.cpp
index 55fe249..4c43546 100644
--- a/lib/cpp/test/OptionalRequiredTest.cpp
+++ b/lib/cpp/test/OptionalRequiredTest.cpp
@@ -40,7 +40,7 @@
 void trywrite(const Struct& s, bool should_work) {
   bool worked;
   try {
-    TBinaryProtocol protocol(stdcxx::shared_ptr<TTransport>(new TMemoryBuffer));
+    TBinaryProtocol protocol(std::shared_ptr<TTransport>(new TMemoryBuffer));
     s.write(&protocol);
     worked = true;
   } catch (TProtocolException & ex) {
@@ -52,7 +52,7 @@
 
 template <typename Struct1, typename Struct2>
 void write_to_read(const Struct1& w, Struct2& r) {
-  TBinaryProtocol protocol(stdcxx::shared_ptr<TTransport>(new TMemoryBuffer));
+  TBinaryProtocol protocol(std::shared_ptr<TTransport>(new TMemoryBuffer));
   w.write(&protocol);
   r.read(&protocol);
 }
@@ -303,7 +303,7 @@
   o1.im_big.push_back(mymap);
   BOOST_CHECK(o1 == o2);
 
-  TBinaryProtocol protocol(stdcxx::shared_ptr<TTransport>(new TMemoryBuffer));
+  TBinaryProtocol protocol(std::shared_ptr<TTransport>(new TMemoryBuffer));
   o1.write(&protocol);
 
   o1.im_big.push_back(mymap);
diff --git a/lib/cpp/test/RecursiveTest.cpp b/lib/cpp/test/RecursiveTest.cpp
index ce5569b..15f234c 100644
--- a/lib/cpp/test/RecursiveTest.cpp
+++ b/lib/cpp/test/RecursiveTest.cpp
@@ -23,7 +23,7 @@
 
 #include "gen-cpp/Recursive_types.h"
 #include <thrift/protocol/TBinaryProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TBufferTransports.h>
 
 #define BOOST_TEST_MODULE RecursiveTest
@@ -31,7 +31,7 @@
 
 using apache::thrift::transport::TMemoryBuffer;
 using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 
 BOOST_AUTO_TEST_CASE(test_recursive_1) {
   shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
diff --git a/lib/cpp/test/RenderedDoubleConstantsTest.cpp b/lib/cpp/test/RenderedDoubleConstantsTest.cpp
new file mode 100644
index 0000000..0ca042b
--- /dev/null
+++ b/lib/cpp/test/RenderedDoubleConstantsTest.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+#define EPSILON 0.0000001
+#include <typeindex>
+#include <typeinfo>
+#include <vector>
+
+#include "gen-cpp/DoubleConstantsTest_constants.h"
+using namespace thrift::test;
+
+#define BOOST_TEST_MODULE RenderedDoubleConstantsTest
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(RenderedDoubleConstantsTest)
+
+BOOST_AUTO_TEST_CASE(test_rendered_double_constants) {
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308;
+    const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43;
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, EPSILON);
+    BOOST_CHECK_CLOSE(
+        g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST,
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, EPSILON);
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST).hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE).hash_code());
+    BOOST_CHECK(
+        typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)
+            .hash_code() ==
+        typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE).hash_code());
+}
+
+BOOST_AUTO_TEST_CASE(test_rendered_double_list) {
+    const std::vector<double> EXPECTED_DOUBLE_LIST{1.0,-100.0,100.0,9223372036854775807.0,-9223372036854775807.0,
+        3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43};
+    BOOST_CHECK_EQUAL(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST.size(), EXPECTED_DOUBLE_LIST.size());
+    for (unsigned int i = 0; i < EXPECTED_DOUBLE_LIST.size(); ++i) {
+        BOOST_CHECK_CLOSE(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST[i], EXPECTED_DOUBLE_LIST[i], EPSILON);
+    }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/lib/cpp/test/SecurityTest.cpp b/lib/cpp/test/SecurityTest.cpp
index 51ee427..982a4f3 100644
--- a/lib/cpp/test/SecurityTest.cpp
+++ b/lib/cpp/test/SecurityTest.cpp
@@ -23,7 +23,7 @@
 #include <boost/foreach.hpp>
 #include <boost/format.hpp>
 #include <boost/thread.hpp>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TSSLServerSocket.h>
 #include <thrift/transport/TSSLSocket.h>
 #include <thrift/transport/TTransport.h>
@@ -40,8 +40,8 @@
 using apache::thrift::transport::TTransportException;
 using apache::thrift::transport::TTransportFactory;
 
-using apache::thrift::stdcxx::bind;
-using apache::thrift::stdcxx::shared_ptr;
+using std::bind;
+using std::shared_ptr;
 
 boost::filesystem::path keyDir;
 boost::filesystem::path certFile(const std::string& filename)
diff --git a/lib/cpp/test/SpecializationTest.cpp b/lib/cpp/test/SpecializationTest.cpp
index a060b4f..008837d 100644
--- a/lib/cpp/test/SpecializationTest.cpp
+++ b/lib/cpp/test/SpecializationTest.cpp
@@ -82,8 +82,8 @@
   stage2.back().message = "nevermore";
   hm.bonks["poe"] = stage2;
 
-  apache::thrift::stdcxx::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
-  apache::thrift::stdcxx::shared_ptr<TProtocol> proto(new MyProtocol(buffer));
+  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
+  std::shared_ptr<TProtocol> proto(new MyProtocol(buffer));
 
   ooe.write(proto.get());
   OneOfEach ooe2;
diff --git a/lib/cpp/test/TBufferBaseTest.cpp b/lib/cpp/test/TBufferBaseTest.cpp
index 4201ddb..430302c 100644
--- a/lib/cpp/test/TBufferBaseTest.cpp
+++ b/lib/cpp/test/TBufferBaseTest.cpp
@@ -21,9 +21,9 @@
 #include <boost/test/auto_unit_test.hpp>
 #include <thrift/transport/TBufferTransports.h>
 #include <thrift/transport/TShortReadTransport.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 using apache::thrift::transport::TMemoryBuffer;
 using apache::thrift::transport::TBufferedTransport;
 using apache::thrift::transport::TFramedTransport;
diff --git a/lib/cpp/test/TFileTransportTest.cpp b/lib/cpp/test/TFileTransportTest.cpp
index 700a1ac..d0c26b3 100644
--- a/lib/cpp/test/TFileTransportTest.cpp
+++ b/lib/cpp/test/TFileTransportTest.cpp
@@ -53,20 +53,6 @@
  * Helper code
  **************************************************************************/
 
-// Provide BOOST_WARN_LT() and BOOST_WARN_GT(), in case we're compiled
-// with an older version of boost
-#ifndef BOOST_WARN_LT
-#define BOOST_WARN_CMP(a, b, op, check_fn)                                                         \
-  check_fn((a)op(b),                                                                               \
-           "check " BOOST_STRINGIZE(a) " " BOOST_STRINGIZE(op) " " BOOST_STRINGIZE(                \
-               b) " failed: " BOOST_STRINGIZE(a) "="                                               \
-           << (a) << " " BOOST_STRINGIZE(b) "=" << (b))
-
-#define BOOST_WARN_LT(a, b) BOOST_WARN_CMP(a, b, <, BOOST_WARN_MESSAGE)
-#define BOOST_WARN_GT(a, b) BOOST_WARN_CMP(a, b, >, BOOST_WARN_MESSAGE)
-#define BOOST_WARN_LT(a, b) BOOST_WARN_CMP(a, b, <, BOOST_WARN_MESSAGE)
-#endif // BOOST_WARN_LT
-
 /**
  * Class to record calls to fsync
  */
@@ -218,7 +204,7 @@
     // If any attempt takes more than 500ms, treat that as a failure.
     // Treat this as a fatal failure, so we'll return now instead of
     // looping over a very slow operation.
-    BOOST_WARN_LT(delta, 500000);
+    BOOST_WARN( delta < 500000 );
 
     // Normally, it takes less than 100ms on my dev box.
     // However, if the box is heavily loaded, some of the test runs
@@ -296,7 +282,7 @@
   for (FsyncLog::CallList::const_iterator it = calls->begin(); it != calls->end(); ++it) {
     if (prev_time) {
       int delta = time_diff(prev_time, &it->time);
-      BOOST_WARN_LT(delta, max_allowed_delta);
+      BOOST_WARN( delta < max_allowed_delta );
     }
     prev_time = &it->time;
   }
@@ -346,7 +332,7 @@
     // Use a fatal fail so we break out early, rather than continuing to make
     // many more slow flush() calls.
     int delta = time_diff(&start, &now);
-    BOOST_WARN_LT(delta, 2000000);
+    BOOST_WARN( delta < 2000000 );
   }
 }
 
diff --git a/lib/cpp/test/TMemoryBufferTest.cpp b/lib/cpp/test/TMemoryBufferTest.cpp
index 9492f69..9206872 100644
--- a/lib/cpp/test/TMemoryBufferTest.cpp
+++ b/lib/cpp/test/TMemoryBufferTest.cpp
@@ -22,7 +22,7 @@
 #include <climits>
 #include <vector>
 #include <thrift/protocol/TBinaryProtocol.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TBufferTransports.h>
 #include "gen-cpp/ThriftTest_types.h"
 
@@ -31,7 +31,7 @@
 using apache::thrift::protocol::TBinaryProtocol;
 using apache::thrift::transport::TMemoryBuffer;
 using apache::thrift::transport::TTransportException;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::cout;
 using std::endl;
 using std::string;
@@ -111,7 +111,7 @@
 
 BOOST_AUTO_TEST_CASE(test_default_maximum_buffer_size)
 {
-  BOOST_CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), TMemoryBuffer().getMaxBufferSize());
+  BOOST_CHECK_EQUAL((std::numeric_limits<uint32_t>::max)(), TMemoryBuffer().getMaxBufferSize());
 }
 
 BOOST_AUTO_TEST_CASE(test_default_buffer_size)
diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp
index 3e9700f..330380b 100644
--- a/lib/cpp/test/TNonblockingSSLServerTest.cpp
+++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp
@@ -19,8 +19,6 @@
 
 #define BOOST_TEST_MODULE TNonblockingSSLServerTest
 #include <boost/test/unit_test.hpp>
-#include <boost/smart_ptr.hpp>
-#include <boost/shared_ptr.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/format.hpp>
 
@@ -105,8 +103,8 @@
 BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL)
 #endif
 
-stdcxx::shared_ptr<TSSLSocketFactory> createServerSocketFactory() {
-  stdcxx::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
+std::shared_ptr<TSSLSocketFactory> createServerSocketFactory() {
+  std::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
 
   pServerSocketFactory.reset(new TSSLSocketFactory());
   pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
@@ -116,8 +114,8 @@
   return pServerSocketFactory;
 }
 
-stdcxx::shared_ptr<TSSLSocketFactory> createClientSocketFactory() {
-  stdcxx::shared_ptr<TSSLSocketFactory> pClientSocketFactory;
+std::shared_ptr<TSSLSocketFactory> createClientSocketFactory() {
+  std::shared_ptr<TSSLSocketFactory> pClientSocketFactory;
 
   pClientSocketFactory.reset(new TSSLSocketFactory());
   pClientSocketFactory->authenticate(true);
@@ -145,12 +143,12 @@
 
   struct Runner : public apache::thrift::concurrency::Runnable {
     int port;
-    stdcxx::shared_ptr<event_base> userEventBase;
-    stdcxx::shared_ptr<TProcessor> processor;
-    stdcxx::shared_ptr<server::TNonblockingServer> server;
-    stdcxx::shared_ptr<ListenEventHandler> listenHandler;
-    stdcxx::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
-    stdcxx::shared_ptr<transport::TNonblockingSSLServerSocket> socket;
+    std::shared_ptr<event_base> userEventBase;
+    std::shared_ptr<TProcessor> processor;
+    std::shared_ptr<server::TNonblockingServer> server;
+    std::shared_ptr<ListenEventHandler> listenHandler;
+    std::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
+    std::shared_ptr<transport::TNonblockingSSLServerSocket> socket;
     Mutex mutex_;
 
     Runner() {
@@ -198,7 +196,7 @@
   };
 
 protected:
-  Fixture() : processor(new test::ParentServiceProcessor(stdcxx::make_shared<Handler>())) {}
+  Fixture() : processor(new test::ParentServiceProcessor(std::make_shared<Handler>())) {}
 
   ~Fixture() {
     if (server) {
@@ -214,14 +212,14 @@
   }
 
   int startServer(int port) {
-    stdcxx::shared_ptr<Runner> runner(new Runner);
+    std::shared_ptr<Runner> runner(new Runner);
     runner->port = port;
     runner->processor = processor;
     runner->userEventBase = userEventBase_;
 
-    apache::thrift::stdcxx::scoped_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory(
+    std::unique_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory(
         new apache::thrift::concurrency::PlatformThreadFactory(
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
             concurrency::PlatformThreadFactory::OTHER, concurrency::PlatformThreadFactory::NORMAL,
             1,
 #endif
@@ -235,11 +233,11 @@
   }
 
   bool canCommunicate(int serverPort) {
-    stdcxx::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
-    stdcxx::shared_ptr<TSSLSocket> socket = pClientSocketFactory->createSocket("localhost", serverPort);
+    std::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
+    std::shared_ptr<TSSLSocket> socket = pClientSocketFactory->createSocket("localhost", serverPort);
     socket->open();
-    test::ParentServiceClient client(stdcxx::make_shared<protocol::TBinaryProtocol>(
-        stdcxx::make_shared<transport::TFramedTransport>(socket)));
+    test::ParentServiceClient client(std::make_shared<protocol::TBinaryProtocol>(
+        std::make_shared<transport::TFramedTransport>(socket)));
     client.addString("foo");
     std::vector<std::string> strings;
     client.getStrings(strings);
@@ -247,12 +245,12 @@
   }
 
 private:
-  stdcxx::shared_ptr<event_base> userEventBase_;
-  stdcxx::shared_ptr<test::ParentServiceProcessor> processor;
+  std::shared_ptr<event_base> userEventBase_;
+  std::shared_ptr<test::ParentServiceProcessor> processor;
 protected:
-  stdcxx::shared_ptr<server::TNonblockingServer> server;
+  std::shared_ptr<server::TNonblockingServer> server;
 private:
-  stdcxx::shared_ptr<apache::thrift::concurrency::Thread> thread;
+  std::shared_ptr<apache::thrift::concurrency::Thread> thread;
 
 };
 
diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp
index 74ffd1d..f0bb283 100644
--- a/lib/cpp/test/TNonblockingServerTest.cpp
+++ b/lib/cpp/test/TNonblockingServerTest.cpp
@@ -19,12 +19,12 @@
 
 #define BOOST_TEST_MODULE TNonblockingServerTest
 #include <boost/test/unit_test.hpp>
+#include <memory>
 
 #include "thrift/concurrency/Monitor.h"
 #include "thrift/concurrency/Thread.h"
 #include "thrift/server/TNonblockingServer.h"
 #include "thrift/transport/TNonblockingServerSocket.h"
-#include "thrift/stdcxx.h"
 
 #include "gen-cpp/ParentService.h"
 
@@ -38,8 +38,8 @@
 using apache::thrift::concurrency::Thread;
 using apache::thrift::concurrency::ThreadFactory;
 using apache::thrift::server::TServerEventHandler;
-using apache::thrift::stdcxx::make_shared;
-using apache::thrift::stdcxx::shared_ptr;
+using std::make_shared;
+using std::shared_ptr;
 
 using namespace apache::thrift;
 
@@ -148,7 +148,7 @@
 
     shared_ptr<ThreadFactory> threadFactory(
         new PlatformThreadFactory(
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
             PlatformThreadFactory::OTHER, PlatformThreadFactory::NORMAL,
             1,
 #endif
@@ -178,7 +178,7 @@
 protected:
   shared_ptr<server::TNonblockingServer> server;
 private:
-  shared_ptr<concurrency::Thread> thread;
+  shared_ptr<apache::thrift::concurrency::Thread> thread;
 
 };
 
diff --git a/lib/cpp/test/TPipeInterruptTest.cpp b/lib/cpp/test/TPipeInterruptTest.cpp
index 232e4bb..2423f56 100644
--- a/lib/cpp/test/TPipeInterruptTest.cpp
+++ b/lib/cpp/test/TPipeInterruptTest.cpp
@@ -27,7 +27,7 @@
 #include <boost/thread/thread.hpp>
 #include <thrift/transport/TPipe.h>
 #include <thrift/transport/TPipeServer.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 using apache::thrift::transport::TPipeServer;
 using apache::thrift::transport::TPipe;
@@ -52,7 +52,7 @@
   {
     for (;;)
     {
-      stdcxx::shared_ptr<TTransport> temp = pipe->accept();
+      std::shared_ptr<TTransport> temp = pipe->accept();
     }
   }
   catch (...) {/*just want to make sure nothing crashes*/ }
@@ -70,8 +70,8 @@
   {
     TPipeServer pipeServer("TPipeInterruptTest");
     pipeServer.listen();
-    boost::thread acceptThread(stdcxx::bind(acceptWorker, &pipeServer));
-    boost::thread interruptThread(stdcxx::bind(interruptWorker, &pipeServer));
+    boost::thread acceptThread(std::bind(acceptWorker, &pipeServer));
+    boost::thread interruptThread(std::bind(interruptWorker, &pipeServer));
     try
     {
       for (;;)
diff --git a/lib/cpp/test/TPipedTransportTest.cpp b/lib/cpp/test/TPipedTransportTest.cpp
index a3ce662..f3091a4 100644
--- a/lib/cpp/test/TPipedTransportTest.cpp
+++ b/lib/cpp/test/TPipedTransportTest.cpp
@@ -18,7 +18,7 @@
  */
 
 #include <thrift/Thrift.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TBufferTransports.h>
 
@@ -31,9 +31,9 @@
 using namespace apache::thrift;
 
 BOOST_AUTO_TEST_CASE(test_read_write) {
-  stdcxx::shared_ptr<TMemoryBuffer> underlying(new TMemoryBuffer);
-  stdcxx::shared_ptr<TMemoryBuffer> pipe(new TMemoryBuffer);
-  stdcxx::shared_ptr<TPipedTransport> trans(new TPipedTransport(underlying, pipe));
+  std::shared_ptr<TMemoryBuffer> underlying(new TMemoryBuffer);
+  std::shared_ptr<TMemoryBuffer> pipe(new TMemoryBuffer);
+  std::shared_ptr<TPipedTransport> trans(new TPipedTransport(underlying, pipe));
 
   uint8_t buffer[4];
 
diff --git a/lib/cpp/test/TSSLSocketInterruptTest.cpp b/lib/cpp/test/TSSLSocketInterruptTest.cpp
index 85f6c39..33f686c 100644
--- a/lib/cpp/test/TSSLSocketInterruptTest.cpp
+++ b/lib/cpp/test/TSSLSocketInterruptTest.cpp
@@ -24,7 +24,7 @@
 #include <boost/thread/thread.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/format.hpp>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/transport/TSSLSocket.h>
 #include <thrift/transport/TSSLServerSocket.h>
 #ifdef __linux__
@@ -37,8 +37,8 @@
 using apache::thrift::transport::TTransportException;
 using apache::thrift::transport::TSSLSocketFactory;
 
-using apache::thrift::stdcxx::static_pointer_cast;
-using apache::thrift::stdcxx::shared_ptr;
+using std::static_pointer_cast;
+using std::shared_ptr;
 
 BOOST_AUTO_TEST_SUITE(TSSLSocketInterruptTest)
 
@@ -146,7 +146,7 @@
   shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
   clientSock->open();
   shared_ptr<TTransport> accepted = sock1.accept();
-  boost::thread readThread(apache::thrift::stdcxx::bind(readerWorkerMustThrow, accepted));
+  boost::thread readThread(std::bind(readerWorkerMustThrow, accepted));
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // readThread is practically guaranteed to be blocking now
   sock1.interruptChildren();
@@ -166,7 +166,7 @@
   shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
   clientSock->open();
   shared_ptr<TTransport> accepted = sock1.accept();
-  boost::thread readThread(apache::thrift::stdcxx::bind(readerWorkerMustThrow, accepted));
+  boost::thread readThread(std::bind(readerWorkerMustThrow, accepted));
   clientSock->write((const uint8_t*)"0", 1);
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // readThread is practically guaranteed to be blocking now
@@ -189,7 +189,7 @@
   clientSock->open();
   shared_ptr<TTransport> accepted = sock1.accept();
   static_pointer_cast<TSSLSocket>(accepted)->setRecvTimeout(1000);
-  boost::thread readThread(apache::thrift::stdcxx::bind(readerWorker, accepted, 0));
+  boost::thread readThread(std::bind(readerWorker, accepted, 0));
   clientSock->write((const uint8_t*)"0", 1);
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // readThread is practically guaranteed to be blocking here
@@ -241,7 +241,7 @@
   shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
   clientSock->open();
   shared_ptr<TTransport> accepted = sock1.accept();
-  boost::thread peekThread(apache::thrift::stdcxx::bind(peekerWorkerInterrupt, accepted));
+  boost::thread peekThread(std::bind(peekerWorkerInterrupt, accepted));
   clientSock->write((const uint8_t*)"0", 1);
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // peekThread is practically guaranteed to be blocking now
@@ -264,7 +264,7 @@
   clientSock->open();
   shared_ptr<TTransport> accepted = sock1.accept();
   static_pointer_cast<TSSLSocket>(accepted)->setRecvTimeout(1000);
-  boost::thread peekThread(apache::thrift::stdcxx::bind(peekerWorker, accepted, false));
+  boost::thread peekThread(std::bind(peekerWorker, accepted, false));
   clientSock->write((const uint8_t*)"0", 1);
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // peekThread is practically guaranteed to be blocking now
diff --git a/lib/cpp/test/TServerIntegrationTest.cpp b/lib/cpp/test/TServerIntegrationTest.cpp
index 5f7b2e8..7976c8b 100644
--- a/lib/cpp/test/TServerIntegrationTest.cpp
+++ b/lib/cpp/test/TServerIntegrationTest.cpp
@@ -18,8 +18,8 @@
  */
 
 #define BOOST_TEST_MODULE TServerIntegrationTest
+#include <atomic>
 #include <boost/test/auto_unit_test.hpp>
-#include <boost/atomic.hpp>
 #include <boost/date_time/posix_time/ptime.hpp>
 #include <boost/foreach.hpp>
 #include <boost/format.hpp>
@@ -27,7 +27,7 @@
 #include <thrift/server/TSimpleServer.h>
 #include <thrift/server/TThreadPoolServer.h>
 #include <thrift/server/TThreadedServer.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/transport/TServerSocket.h>
 #include <thrift/transport/TSocket.h>
@@ -55,9 +55,9 @@
 using apache::thrift::server::TSimpleServer;
 using apache::thrift::server::TThreadPoolServer;
 using apache::thrift::server::TThreadedServer;
-using apache::thrift::stdcxx::dynamic_pointer_cast;
-using apache::thrift::stdcxx::make_shared;
-using apache::thrift::stdcxx::shared_ptr;
+using std::dynamic_pointer_cast;
+using std::make_shared;
+using std::shared_ptr;
 using apache::thrift::test::ParentServiceClient;
 using apache::thrift::test::ParentServiceIf;
 using apache::thrift::test::ParentServiceIfFactory;
@@ -177,7 +177,7 @@
   }
 
   void startServer() {
-    pServerThread.reset(new boost::thread(apache::thrift::stdcxx::bind(&TServerType::serve, pServer.get())));
+    pServerThread.reset(new boost::thread(std::bind(&TServerType::serve, pServer.get())));
 
     // block until listen() completes so clients will be able to connect
     Synchronized sync(*(pEventHandler.get()));
@@ -235,7 +235,7 @@
       pClientSock->open();
       client.incrementGeneration();
       holdThreads.push_back(shared_ptr<boost::thread>(
-          new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
+          new boost::thread(std::bind(&TServerIntegrationTestFixture::delayClose,
                                         this,
                                         pClientSock,
                                         milliseconds(10 * numToMake)))));
@@ -284,7 +284,7 @@
     std::vector<shared_ptr<boost::thread> > holdThreads;
     for (int64_t i = 0; i < numToMake; ++i) {
       holdThreads.push_back(shared_ptr<boost::thread>(
-        new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::stressor, this))));
+        new boost::thread(std::bind(&TServerIntegrationTestFixture::stressor, this))));
     }
 
     boost::this_thread::sleep(duration);
@@ -310,10 +310,10 @@
       shared_ptr<TProtocol> pProtocol(new TBinaryProtocol(pSocket));
       ParentServiceClient client(pProtocol);
       pSocket->open();
-      bStressConnectionCount.fetch_add(1, boost::memory_order_relaxed);
+      bStressConnectionCount.fetch_add(1, std::memory_order_relaxed);
       for (int i = 0; i < rand() % 1000; ++i) {
       client.incrementGeneration();
-        bStressRequestCount.fetch_add(1, boost::memory_order_relaxed);
+        bStressRequestCount.fetch_add(1, std::memory_order_relaxed);
       }
     }
   }
@@ -321,9 +321,9 @@
   shared_ptr<TServerType> pServer;
   shared_ptr<TServerReadyEventHandler> pEventHandler;
   shared_ptr<boost::thread> pServerThread;
-  boost::atomic<bool> bStressDone;
-  boost::atomic_int64_t bStressConnectionCount;
-  boost::atomic_int64_t bStressRequestCount;
+  std::atomic<bool> bStressDone;
+  std::atomic<int64_t> bStressConnectionCount;
+  std::atomic<int64_t> bStressRequestCount;
 };
 
 template <class TServerType>
@@ -479,11 +479,11 @@
   // Ensure they have been accepted
   blockUntilAccepted(2);
 
-  boost::thread t1(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
+  boost::thread t1(std::bind(&TServerIntegrationTestFixture::delayClose,
                                this,
                                pClientSock1,
                                milliseconds(250)));
-  boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
+  boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose,
                                this,
                                pClientSock2,
                                milliseconds(250)));
@@ -517,7 +517,7 @@
   BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
 
   // a third client cannot connect until one of the other two closes
-  boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
+  boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose,
                                this,
                                pClientSock2,
                                milliseconds(250)));
diff --git a/lib/cpp/test/TServerSocketTest.cpp b/lib/cpp/test/TServerSocketTest.cpp
index a191147..bec6d47 100644
--- a/lib/cpp/test/TServerSocketTest.cpp
+++ b/lib/cpp/test/TServerSocketTest.cpp
@@ -20,7 +20,7 @@
 #include <boost/test/auto_unit_test.hpp>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TServerSocket.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 #include "TTransportCheckThrow.h"
 #include <iostream>
 
@@ -28,7 +28,7 @@
 using apache::thrift::transport::TSocket;
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 
 BOOST_AUTO_TEST_SUITE(TServerSocketTest)
 
diff --git a/lib/cpp/test/TServerTransportTest.cpp b/lib/cpp/test/TServerTransportTest.cpp
index dc6aede..539bd28 100644
--- a/lib/cpp/test/TServerTransportTest.cpp
+++ b/lib/cpp/test/TServerTransportTest.cpp
@@ -20,12 +20,12 @@
 #include <boost/test/auto_unit_test.hpp>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TServerTransport.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 using apache::thrift::transport::TServerTransport;
 using apache::thrift::transport::TTransport;
 using apache::thrift::transport::TTransportException;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 
 BOOST_AUTO_TEST_SUITE(TServerTransportTest)
 
diff --git a/lib/cpp/test/TSocketInterruptTest.cpp b/lib/cpp/test/TSocketInterruptTest.cpp
index 3a189cc..366242f 100644
--- a/lib/cpp/test/TSocketInterruptTest.cpp
+++ b/lib/cpp/test/TSocketInterruptTest.cpp
@@ -25,7 +25,7 @@
 #include <boost/thread/thread.hpp>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TServerSocket.h>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 using apache::thrift::transport::TServerSocket;
 using apache::thrift::transport::TSocket;
@@ -35,12 +35,12 @@
 
 BOOST_AUTO_TEST_SUITE(TSocketInterruptTest)
 
-void readerWorker(stdcxx::shared_ptr<TTransport> tt, uint32_t expectedResult) {
+void readerWorker(std::shared_ptr<TTransport> tt, uint32_t expectedResult) {
   uint8_t buf[4];
   BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4));
 }
 
-void readerWorkerMustThrow(stdcxx::shared_ptr<TTransport> tt) {
+void readerWorkerMustThrow(std::shared_ptr<TTransport> tt) {
   try {
     uint8_t buf[4];
     tt->read(buf, 4);
@@ -56,8 +56,8 @@
   int port = sock1.getPort();
   TSocket clientSock("localhost", port);
   clientSock.open();
-  stdcxx::shared_ptr<TTransport> accepted = sock1.accept();
-  boost::thread readThread(stdcxx::bind(readerWorkerMustThrow, accepted));
+  std::shared_ptr<TTransport> accepted = sock1.accept();
+  boost::thread readThread(std::bind(readerWorkerMustThrow, accepted));
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // readThread is practically guaranteed to be blocking now
   sock1.interruptChildren();
@@ -75,8 +75,8 @@
   int port = sock1.getPort();
   TSocket clientSock("localhost", port);
   clientSock.open();
-  stdcxx::shared_ptr<TTransport> accepted = sock1.accept();
-  boost::thread readThread(stdcxx::bind(readerWorker, accepted, 0));
+  std::shared_ptr<TTransport> accepted = sock1.accept();
+  boost::thread readThread(std::bind(readerWorker, accepted, 0));
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // readThread is practically guaranteed to be blocking here
   sock1.interruptChildren();
@@ -97,7 +97,7 @@
   sock1.close();
 }
 
-void peekerWorker(stdcxx::shared_ptr<TTransport> tt, bool expectedResult) {
+void peekerWorker(std::shared_ptr<TTransport> tt, bool expectedResult) {
   BOOST_CHECK_EQUAL(expectedResult, tt->peek());
 }
 
@@ -107,9 +107,9 @@
   int port = sock1.getPort();
   TSocket clientSock("localhost", port);
   clientSock.open();
-  stdcxx::shared_ptr<TTransport> accepted = sock1.accept();
+  std::shared_ptr<TTransport> accepted = sock1.accept();
   // peek() will return false if child is interrupted
-  boost::thread peekThread(stdcxx::bind(peekerWorker, accepted, false));
+  boost::thread peekThread(std::bind(peekerWorker, accepted, false));
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // peekThread is practically guaranteed to be blocking now
   sock1.interruptChildren();
@@ -127,9 +127,9 @@
   int port = sock1.getPort();
   TSocket clientSock("localhost", port);
   clientSock.open();
-  stdcxx::shared_ptr<TTransport> accepted = sock1.accept();
+  std::shared_ptr<TTransport> accepted = sock1.accept();
   // peek() will return false when remote side is closed
-  boost::thread peekThread(stdcxx::bind(peekerWorker, accepted, false));
+  boost::thread peekThread(std::bind(peekerWorker, accepted, false));
   boost::this_thread::sleep(boost::posix_time::milliseconds(50));
   // peekThread is practically guaranteed to be blocking now
   sock1.interruptChildren();
diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp
index d6ab457..ce19544 100644
--- a/lib/cpp/test/TransportTest.cpp
+++ b/lib/cpp/test/TransportTest.cpp
@@ -26,7 +26,6 @@
 #endif
 #include <sstream>
 #include <fstream>
-#include <thrift/stdcxx.h>
 
 #include <boost/mpl/list.hpp>
 #include <boost/shared_array.hpp>
@@ -114,7 +113,7 @@
   std::string describe() const { return generator_->describe(); }
 
 private:
-  stdcxx::shared_ptr<SizeGenerator> generator_;
+  std::shared_ptr<SizeGenerator> generator_;
 };
 
 /**************************************************************************
@@ -137,8 +136,8 @@
 
   CoupledTransports() : in(), out() {}
 
-  stdcxx::shared_ptr<Transport_> in;
-  stdcxx::shared_ptr<Transport_> out;
+  std::shared_ptr<Transport_> in;
+  std::shared_ptr<Transport_> out;
 
 private:
   CoupledTransports(const CoupledTransports&);
@@ -155,7 +154,7 @@
     out = buf;
   }
 
-  stdcxx::shared_ptr<TMemoryBuffer> buf;
+  std::shared_ptr<TMemoryBuffer> buf;
 };
 
 /**
@@ -341,11 +340,11 @@
  **************************************************************************/
 
 struct TriggerInfo {
-  TriggerInfo(int seconds, const stdcxx::shared_ptr<TTransport>& transport, uint32_t writeLength)
+  TriggerInfo(int seconds, const std::shared_ptr<TTransport>& transport, uint32_t writeLength)
     : timeoutSeconds(seconds), transport(transport), writeLength(writeLength), next(NULL) {}
 
   int timeoutSeconds;
-  stdcxx::shared_ptr<TTransport> transport;
+  std::shared_ptr<TTransport> transport;
   uint32_t writeLength;
   TriggerInfo* next;
 };
@@ -420,7 +419,7 @@
  * to the end.)
  */
 void add_trigger(unsigned int seconds,
-                 const stdcxx::shared_ptr<TTransport>& transport,
+                 const std::shared_ptr<TTransport>& transport,
                  uint32_t write_len) {
   TriggerInfo* info = new TriggerInfo(seconds, transport, write_len);
   {
@@ -460,7 +459,7 @@
 }
 
 void set_trigger(unsigned int seconds,
-                 const stdcxx::shared_ptr<TTransport>& transport,
+                 const std::shared_ptr<TTransport>& transport,
                  uint32_t write_len) {
   clear_triggers();
   add_trigger(seconds, transport, write_len);
@@ -976,11 +975,11 @@
          << rChunkSizeGen.describe() << ", " << maxOutstanding << ")";
 
 #if (BOOST_VERSION >= 105900)
-    stdcxx::function<void ()> test_func
+    std::function<void ()> test_func
 #else
     boost::unit_test::callback0<> test_func
 #endif
-        = stdcxx::bind(test_rw<CoupledTransports>,
+        = std::bind(test_rw<CoupledTransports>,
                                        totalSize,
                                        wSizeGen,
                                        rSizeGen,
@@ -1026,7 +1025,7 @@
  **************************************************************************/
 
 struct global_fixture {
-  stdcxx::shared_ptr<apache::thrift::concurrency::Thread> alarmThread_;
+  std::shared_ptr<apache::thrift::concurrency::Thread> alarmThread_;
   global_fixture() {
 #if _WIN32
     apache::thrift::transport::TWinsockSingleton::create();
diff --git a/lib/cpp/test/ZlibTest.cpp b/lib/cpp/test/ZlibTest.cpp
index ea54487..c826814 100644
--- a/lib/cpp/test/ZlibTest.cpp
+++ b/lib/cpp/test/ZlibTest.cpp
@@ -36,7 +36,7 @@
 #include <cstddef>
 #include <fstream>
 #include <iostream>
-#include <thrift/stdcxx.h>
+#include <memory>
 
 #include <boost/random.hpp>
 #include <boost/shared_array.hpp>
@@ -47,7 +47,7 @@
 #include <thrift/transport/TZlibTransport.h>
 
 using namespace apache::thrift::transport;
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 using std::string;
 
 boost::mt19937 rng;
@@ -347,8 +347,8 @@
   do {                                                                                             \
     ::std::ostringstream name_ss;                                                                  \
     name_ss << name << "-" << BOOST_STRINGIZE(_FUNC);                                              \
-    ::apache::thrift::stdcxx::function<void ()> test_func =                                        \
-        ::apache::thrift::stdcxx::bind(_FUNC, ##__VA_ARGS__);                                      \
+    ::std::function<void ()> test_func =                                        \
+        ::std::bind(_FUNC, ##__VA_ARGS__);                                      \
     ::boost::unit_test::test_case* tc                                                              \
         = ::boost::unit_test::make_test_case(test_func, name_ss.str(), __FILE__, __LINE__);        \
     (suite)->add(tc);                                                                              \
@@ -359,7 +359,7 @@
     ::std::ostringstream name_ss;                                                                  \
     name_ss << name << "-" << BOOST_STRINGIZE(_FUNC);                                              \
     ::boost::unit_test::test_case* tc                                                              \
-        = ::boost::unit_test::make_test_case(::apache::thrift::stdcxx::bind(_FUNC,                 \
+        = ::boost::unit_test::make_test_case(::std::bind(_FUNC,                 \
                                                                             ##__VA_ARGS__),        \
                                              name_ss.str());                                       \
     (suite)->add(tc);                                                                              \
diff --git a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp b/lib/cpp/test/concurrency/RWMutexStarveTest.cpp
index 849e078..985a230 100644
--- a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp
+++ b/lib/cpp/test/concurrency/RWMutexStarveTest.cpp
@@ -23,9 +23,9 @@
 
 #include "thrift/concurrency/Mutex.h"
 #include "thrift/concurrency/PosixThreadFactory.h"
-#include <thrift/stdcxx.h>
+#include <memory>
 
-using apache::thrift::stdcxx::shared_ptr;
+using std::shared_ptr;
 using boost::unit_test::test_suite;
 using boost::unit_test::framework::master_test_suite;
 
diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp
index df5099d..fc0ba7f 100644
--- a/lib/cpp/test/concurrency/Tests.cpp
+++ b/lib/cpp/test/concurrency/Tests.cpp
@@ -27,7 +27,7 @@
 
 // The test weight, where 10 is 10 times more threads than baseline
 // and the baseline is optimized for running in valgrind
-static size_t WEIGHT = 10;
+static int WEIGHT = 10;
 
 int main(int argc, char** argv) {
 
diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h
index 48330f3..ba98502 100644
--- a/lib/cpp/test/concurrency/ThreadFactoryTests.h
+++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h
@@ -33,7 +33,7 @@
 namespace concurrency {
 namespace test {
 
-using stdcxx::shared_ptr;
+using std::shared_ptr;
 using namespace apache::thrift::concurrency;
 
 /**
diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h
index 9ecd6ba..d6c092d 100644
--- a/lib/cpp/test/concurrency/ThreadManagerTests.h
+++ b/lib/cpp/test/concurrency/ThreadManagerTests.h
@@ -36,8 +36,8 @@
 
 using namespace apache::thrift::concurrency;
 
-static std::deque<stdcxx::shared_ptr<Runnable> > m_expired;
-static void expiredNotifier(stdcxx::shared_ptr<Runnable> runnable)
+static std::deque<std::shared_ptr<Runnable> > m_expired;
+static void expiredNotifier(std::shared_ptr<Runnable> runnable)
 {
   m_expired.push_back(runnable);
 }
@@ -111,7 +111,7 @@
     shared_ptr<PlatformThreadFactory> threadFactory
         = shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory(false));
 
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
     threadFactory->setPriority(PosixThreadFactory::HIGHEST);
 #endif
     threadManager->threadFactory(threadFactory);
@@ -260,7 +260,7 @@
       shared_ptr<PlatformThreadFactory> threadFactory
           = shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
 
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
       threadFactory->setPriority(PosixThreadFactory::HIGHEST);
 #endif
       threadManager->threadFactory(threadFactory);
@@ -401,7 +401,7 @@
       return false;
     }
 
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
     // test once with a detached thread factory and once with a joinable thread factory
 
     shared_ptr<PosixThreadFactory> threadFactory
@@ -426,7 +426,7 @@
     shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(1);
     threadManager->threadFactory(threadFactory);
 
-#if !USE_BOOST_THREAD && !USE_STD_THREAD
+#if !USE_STD_THREAD
     threadFactory->setPriority(PosixThreadFactory::HIGHEST);
 
     // verify we cannot change the thread factory to one with the opposite detached setting
@@ -452,7 +452,7 @@
     std::cout << "\t\t\t\tstarting.. " << std::endl;
 
     threadManager->start();
-    threadManager->setExpireCallback(expiredNotifier); // apache::thrift::stdcxx::bind(&ThreadManagerTests::expiredNotifier, this));
+    threadManager->setExpireCallback(expiredNotifier); // std::bind(&ThreadManagerTests::expiredNotifier, this));
 
 #define EXPECT(FUNC, COUNT) { size_t c = FUNC; if (c != COUNT) { std::cerr << "expected " #FUNC" to be " #COUNT ", but was " << c << std::endl; return false; } }
 
diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h
index 3779b0d..1c52c47 100644
--- a/lib/cpp/test/concurrency/TimerManagerTests.h
+++ b/lib/cpp/test/concurrency/TimerManagerTests.h
@@ -79,14 +79,13 @@
         = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout));
 
     {
-
       TimerManager timerManager;
-
       timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
-
       timerManager.start();
-
-      assert(timerManager.state() == TimerManager::STARTED);
+      if (timerManager.state() != TimerManager::STARTED) {
+        std::cerr << "timerManager is not in the STARTED state, but should be" << std::endl;
+        return false;
+      }
 
       // Don't create task yet, because its constructor sets the expected completion time, and we
       // need to delay between inserting the two tasks into the run queue.
@@ -94,34 +93,27 @@
 
       {
         Synchronized s(_monitor);
-
         timerManager.add(orphanTask, 10 * timeout);
 
-        try {
-          // Wait for 1 second in order to give timerManager a chance to start sleeping in response
-          // to adding orphanTask. We need to do this so we can verify that adding the second task
-          // kicks the dispatcher out of the current wait and starts the new 1 second wait.
-          _monitor.wait(1000);
-          assert(
-              0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem.");
-        } catch (TimedOutException&) {
-        }
+        THRIFT_SLEEP_USEC(timeout * 1000);
 
         task.reset(new TimerManagerTests::Task(_monitor, timeout));
-
         timerManager.add(task, timeout);
-
         _monitor.wait();
       }
 
-      assert(task->_done);
+      if (!task->_done) {
+        std::cerr << "task is not done, but it should have executed" << std::endl;
+        return false;
+      }
 
       std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl;
     }
 
-    // timerManager.stop(); This is where it happens via destructor
-
-    assert(!orphanTask->_done);
+    if (orphanTask->_done) {
+      std::cerr << "orphan task is done, but it should not have executed" << std::endl;
+      return false;
+    }
 
     return true;
   }
diff --git a/lib/cpp/test/processor/Handlers.h b/lib/cpp/test/processor/Handlers.h
index ad47229..29784d8 100644
--- a/lib/cpp/test/processor/Handlers.h
+++ b/lib/cpp/test/processor/Handlers.h
@@ -29,7 +29,7 @@
 
 class ParentHandler : virtual public ParentServiceIf {
 public:
-  ParentHandler(const stdcxx::shared_ptr<EventLog>& log)
+  ParentHandler(const std::shared_ptr<EventLog>& log)
     : triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {}
 
   int32_t incrementGeneration() {
@@ -136,7 +136,7 @@
   int32_t generation_;
   bool wait_;
   std::vector<std::string> strings_;
-  stdcxx::shared_ptr<EventLog> log_;
+  std::shared_ptr<EventLog> log_;
 };
 
 #ifdef _WIN32
@@ -146,7 +146,7 @@
 
 class ChildHandler : public ParentHandler, virtual public ChildServiceIf {
 public:
-  ChildHandler(const stdcxx::shared_ptr<EventLog>& log) : ParentHandler(log), value_(0) {}
+  ChildHandler(const std::shared_ptr<EventLog>& log) : ParentHandler(log), value_(0) {}
 
   int32_t setValue(const int32_t value) {
     concurrency::Guard g(mutex_);
@@ -174,13 +174,13 @@
 
 struct ConnContext {
 public:
-  ConnContext(stdcxx::shared_ptr<protocol::TProtocol> in,
-              stdcxx::shared_ptr<protocol::TProtocol> out,
+  ConnContext(std::shared_ptr<protocol::TProtocol> in,
+              std::shared_ptr<protocol::TProtocol> out,
               uint32_t id)
     : input(in), output(out), id(id) {}
 
-  stdcxx::shared_ptr<protocol::TProtocol> input;
-  stdcxx::shared_ptr<protocol::TProtocol> output;
+  std::shared_ptr<protocol::TProtocol> input;
+  std::shared_ptr<protocol::TProtocol> output;
   uint32_t id;
 };
 
@@ -196,12 +196,12 @@
 
 class ServerEventHandler : public server::TServerEventHandler {
 public:
-  ServerEventHandler(const stdcxx::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
+  ServerEventHandler(const std::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
 
   virtual void preServe() {}
 
-  virtual void* createContext(stdcxx::shared_ptr<protocol::TProtocol> input,
-                              stdcxx::shared_ptr<protocol::TProtocol> output) {
+  virtual void* createContext(std::shared_ptr<protocol::TProtocol> input,
+                              std::shared_ptr<protocol::TProtocol> output) {
     ConnContext* context = new ConnContext(input, output, nextId_);
     ++nextId_;
     log_->append(EventLog::ET_CONN_CREATED, context->id, 0);
@@ -209,8 +209,8 @@
   }
 
   virtual void deleteContext(void* serverContext,
-                             stdcxx::shared_ptr<protocol::TProtocol> input,
-                             stdcxx::shared_ptr<protocol::TProtocol> output) {
+                             std::shared_ptr<protocol::TProtocol> input,
+                             std::shared_ptr<protocol::TProtocol> output) {
     ConnContext* context = reinterpret_cast<ConnContext*>(serverContext);
 
     if (input != context->input) {
@@ -226,7 +226,7 @@
   }
 
   virtual void processContext(void* serverContext,
-                              stdcxx::shared_ptr<transport::TTransport> transport) {
+                              std::shared_ptr<transport::TTransport> transport) {
 // TODO: We currently don't test the behavior of the processContext()
 // calls.  The various server implementations call processContext() at
 // slightly different times, and it is too annoying to try and account for
@@ -251,12 +251,12 @@
 
 protected:
   uint32_t nextId_;
-  stdcxx::shared_ptr<EventLog> log_;
+  std::shared_ptr<EventLog> log_;
 };
 
 class ProcessorEventHandler : public TProcessorEventHandler {
 public:
-  ProcessorEventHandler(const stdcxx::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
+  ProcessorEventHandler(const std::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
 
   void* getContext(const char* fnName, void* serverContext) {
     ConnContext* connContext = reinterpret_cast<ConnContext*>(serverContext);
@@ -329,7 +329,7 @@
   }
 
   uint32_t nextId_;
-  stdcxx::shared_ptr<EventLog> log_;
+  std::shared_ptr<EventLog> log_;
 };
 }
 }
diff --git a/lib/cpp/test/processor/ProcessorTest.cpp b/lib/cpp/test/processor/ProcessorTest.cpp
index c9e186f..36ce013 100644
--- a/lib/cpp/test/processor/ProcessorTest.cpp
+++ b/lib/cpp/test/processor/ProcessorTest.cpp
@@ -57,13 +57,13 @@
 public:
   typedef TSimpleServer ServerType;
 
-  stdcxx::shared_ptr<TSimpleServer> createServer(
-      const stdcxx::shared_ptr<TProcessor>& processor,
+  std::shared_ptr<TSimpleServer> createServer(
+      const std::shared_ptr<TProcessor>& processor,
       uint16_t port,
-      const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
-    stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
-    return stdcxx::shared_ptr<TSimpleServer>(
+      const std::shared_ptr<TTransportFactory>& transportFactory,
+      const std::shared_ptr<TProtocolFactory>& protocolFactory) {
+    std::shared_ptr<TServerSocket> socket(new TServerSocket(port));
+    return std::shared_ptr<TSimpleServer>(
         new TSimpleServer(processor, socket, transportFactory, protocolFactory));
   }
 };
@@ -72,13 +72,13 @@
 public:
   typedef TThreadedServer ServerType;
 
-  stdcxx::shared_ptr<TThreadedServer> createServer(
-      const stdcxx::shared_ptr<TProcessor>& processor,
+  std::shared_ptr<TThreadedServer> createServer(
+      const std::shared_ptr<TProcessor>& processor,
       uint16_t port,
-      const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
-    stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
-    return stdcxx::shared_ptr<TThreadedServer>(
+      const std::shared_ptr<TTransportFactory>& transportFactory,
+      const std::shared_ptr<TProtocolFactory>& protocolFactory) {
+    std::shared_ptr<TServerSocket> socket(new TServerSocket(port));
+    return std::shared_ptr<TThreadedServer>(
         new TThreadedServer(processor, socket, transportFactory, protocolFactory));
   }
 };
@@ -87,19 +87,19 @@
 public:
   typedef TThreadPoolServer ServerType;
 
-  stdcxx::shared_ptr<TThreadPoolServer> createServer(
-      const stdcxx::shared_ptr<TProcessor>& processor,
+  std::shared_ptr<TThreadPoolServer> createServer(
+      const std::shared_ptr<TProcessor>& processor,
       uint16_t port,
-      const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
-    stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
+      const std::shared_ptr<TTransportFactory>& transportFactory,
+      const std::shared_ptr<TProtocolFactory>& protocolFactory) {
+    std::shared_ptr<TServerSocket> socket(new TServerSocket(port));
 
-    stdcxx::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
-    stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
+    std::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
+    std::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
     threadManager->threadFactory(threadFactory);
     threadManager->start();
 
-    return stdcxx::shared_ptr<TThreadPoolServer>(
+    return std::shared_ptr<TThreadPoolServer>(
         new TThreadPoolServer(processor, socket, transportFactory, protocolFactory, threadManager));
   }
 };
@@ -108,11 +108,11 @@
 public:
   typedef TNonblockingServer ServerType;
 
-  stdcxx::shared_ptr<TNonblockingServer> createServer(
-      const stdcxx::shared_ptr<TProcessor>& processor,
+  std::shared_ptr<TNonblockingServer> createServer(
+      const std::shared_ptr<TProcessor>& processor,
       uint16_t port,
-      const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
+      const std::shared_ptr<TTransportFactory>& transportFactory,
+      const std::shared_ptr<TProtocolFactory>& protocolFactory) {
     // TNonblockingServer automatically uses TFramedTransport.
     // Raise an exception if the supplied transport factory is not a
     // TFramedTransportFactory
@@ -122,13 +122,13 @@
       throw TException("TNonblockingServer must use TFramedTransport");
     }
 
-    stdcxx::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
-    stdcxx::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
-    stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
+    std::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
+    std::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
+    std::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
     threadManager->threadFactory(threadFactory);
     threadManager->start();
 
-    return stdcxx::shared_ptr<TNonblockingServer>(
+    return std::shared_ptr<TNonblockingServer>(
         new TNonblockingServer(processor, protocolFactory, socket, threadManager));
   }
 };
@@ -137,11 +137,11 @@
 public:
   typedef TNonblockingServer ServerType;
 
-  stdcxx::shared_ptr<TNonblockingServer> createServer(
-      const stdcxx::shared_ptr<TProcessor>& processor,
+  std::shared_ptr<TNonblockingServer> createServer(
+      const std::shared_ptr<TProcessor>& processor,
       uint16_t port,
-      const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
-      const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
+      const std::shared_ptr<TTransportFactory>& transportFactory,
+      const std::shared_ptr<TProtocolFactory>& protocolFactory) {
     // TNonblockingServer automatically uses TFramedTransport.
     // Raise an exception if the supplied transport factory is not a
     // TFramedTransportFactory
@@ -151,10 +151,10 @@
       throw TException("TNonblockingServer must use TFramedTransport");
     }
 
-    stdcxx::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
+    std::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
     // Use a NULL ThreadManager
-    stdcxx::shared_ptr<ThreadManager> threadManager;
-    return stdcxx::shared_ptr<TNonblockingServer>(
+    std::shared_ptr<ThreadManager> threadManager;
+    return std::shared_ptr<TNonblockingServer>(
         new TNonblockingServer(processor, protocolFactory, socket, threadManager));
   }
 };
@@ -244,48 +244,48 @@
     processor_->setEventHandler(processorEventHandler_);
   }
 
-  stdcxx::shared_ptr<TServer> createServer(uint16_t port) {
+  std::shared_ptr<TServer> createServer(uint16_t port) {
     ServerTraits_ serverTraits;
     return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_);
   }
 
-  stdcxx::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
+  std::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
 
   void bindSuccessful(uint16_t port) { port_ = port; }
 
   uint16_t getPort() const { return port_; }
 
-  const stdcxx::shared_ptr<EventLog>& getLog() const { return log_; }
+  const std::shared_ptr<EventLog>& getLog() const { return log_; }
 
-  const stdcxx::shared_ptr<Handler>& getHandler() const { return handler_; }
+  const std::shared_ptr<Handler>& getHandler() const { return handler_; }
 
-  stdcxx::shared_ptr<Client> createClient() {
+  std::shared_ptr<Client> createClient() {
     typedef typename ServiceTraits_::Protocol Protocol;
 
-    stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port_));
-    stdcxx::shared_ptr<Transport_> transport(new Transport_(socket));
-    stdcxx::shared_ptr<Protocol> protocol(new Protocol(transport));
+    std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port_));
+    std::shared_ptr<Transport_> transport(new Transport_(socket));
+    std::shared_ptr<Protocol> protocol(new Protocol(transport));
     transport->open();
 
-    stdcxx::shared_ptr<Client> client(new Client(protocol));
+    std::shared_ptr<Client> client(new Client(protocol));
     return client;
   }
 
 private:
   uint16_t port_;
-  stdcxx::shared_ptr<EventLog> log_;
-  stdcxx::shared_ptr<Handler> handler_;
-  stdcxx::shared_ptr<Processor> processor_;
-  stdcxx::shared_ptr<TTransportFactory> transportFactory_;
-  stdcxx::shared_ptr<TProtocolFactory> protocolFactory_;
-  stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
-  stdcxx::shared_ptr<TProcessorEventHandler> processorEventHandler_;
+  std::shared_ptr<EventLog> log_;
+  std::shared_ptr<Handler> handler_;
+  std::shared_ptr<Processor> processor_;
+  std::shared_ptr<TTransportFactory> transportFactory_;
+  std::shared_ptr<TProtocolFactory> protocolFactory_;
+  std::shared_ptr<TServerEventHandler> serverEventHandler_;
+  std::shared_ptr<TProcessorEventHandler> processorEventHandler_;
 };
 
 /**
  * Check that there are no more events in the log
  */
-void checkNoEvents(const stdcxx::shared_ptr<EventLog>& log) {
+void checkNoEvents(const std::shared_ptr<EventLog>& log) {
   // Wait for an event with a very short timeout period.  We don't expect
   // anything to be present, so we will normally wait for the full timeout.
   // On the other hand, a non-zero timeout is nice since it does give a short
@@ -299,7 +299,7 @@
  *
  * Returns the connection ID allocated by the server.
  */
-uint32_t checkNewConnEvents(const stdcxx::shared_ptr<EventLog>& log) {
+uint32_t checkNewConnEvents(const std::shared_ptr<EventLog>& log) {
   // Check for an ET_CONN_CREATED event
   Event event = log->waitForEvent(2500);
   BOOST_CHECK_EQUAL(EventLog::ET_CONN_CREATED, event.type);
@@ -314,7 +314,7 @@
 /**
  * Check for the events that should be logged when a connection is closed.
  */
-void checkCloseEvents(const stdcxx::shared_ptr<EventLog>& log, uint32_t connId) {
+void checkCloseEvents(const std::shared_ptr<EventLog>& log, uint32_t connId) {
   // Check for an ET_CONN_DESTROYED event
   Event event = log->waitForEvent();
   BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type);
@@ -332,7 +332,7 @@
  *
  * Returns the call ID allocated by the server.
  */
-uint32_t checkCallHandlerEvents(const stdcxx::shared_ptr<EventLog>& log,
+uint32_t checkCallHandlerEvents(const std::shared_ptr<EventLog>& log,
                                 uint32_t connId,
                                 EventType callType,
                                 const string& callName) {
@@ -369,7 +369,7 @@
 /**
  * Check for the events that should be after a handler returns.
  */
-void checkCallPostHandlerEvents(const stdcxx::shared_ptr<EventLog>& log,
+void checkCallPostHandlerEvents(const std::shared_ptr<EventLog>& log,
                                 uint32_t connId,
                                 uint32_t callId,
                                 const string& callName) {
@@ -409,7 +409,7 @@
  *
  * Returns the call ID allocated by the server.
  */
-uint32_t checkCallEvents(const stdcxx::shared_ptr<EventLog>& log,
+uint32_t checkCallEvents(const std::shared_ptr<EventLog>& log,
                          uint32_t connId,
                          EventType callType,
                          const string& callName) {
@@ -424,8 +424,8 @@
  */
 
 template <typename State_>
-void testParentService(const stdcxx::shared_ptr<State_>& state) {
-  stdcxx::shared_ptr<typename State_::Client> client = state->createClient();
+void testParentService(const std::shared_ptr<State_>& state) {
+  std::shared_ptr<typename State_::Client> client = state->createClient();
 
   int32_t gen = client->getGeneration();
   int32_t newGen = client->incrementGeneration();
@@ -446,8 +446,8 @@
 }
 
 template <typename State_>
-void testChildService(const stdcxx::shared_ptr<State_>& state) {
-  stdcxx::shared_ptr<typename State_::Client> client = state->createClient();
+void testChildService(const std::shared_ptr<State_>& state) {
+  std::shared_ptr<typename State_::Client> client = state->createClient();
 
   // Test calling some of the parent methids via the a child client
   int32_t gen = client->getGeneration();
@@ -468,7 +468,7 @@
   typedef ServiceState<ServerTraits, ParentServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
   testParentService(state);
@@ -479,7 +479,7 @@
   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
   testParentService(state);
@@ -502,10 +502,10 @@
                        TBufferedTransport> State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
-  const stdcxx::shared_ptr<EventLog>& log = state->getLog();
+  const std::shared_ptr<EventLog>& log = state->getLog();
 
   // Make sure we're at the end of the log
   checkNoEvents(log);
@@ -514,7 +514,7 @@
 
   // Make sure createContext() is called after a connection has been
   // established.  We open a plain socket instead of creating a client.
-  stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", state->getPort()));
+  std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", state->getPort()));
   socket->open();
 
   // Make sure the proper events occurred after a new connection
@@ -635,19 +635,19 @@
   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
-  const stdcxx::shared_ptr<EventLog>& log = state->getLog();
+  const std::shared_ptr<EventLog>& log = state->getLog();
 
   // Create a client
-  stdcxx::shared_ptr<typename State::Client> client1 = state->createClient();
+  std::shared_ptr<typename State::Client> client1 = state->createClient();
 
   // Make sure the expected events were logged
   uint32_t client1Id = checkNewConnEvents(log);
 
   // Create a second client
-  stdcxx::shared_ptr<typename State::Client> client2 = state->createClient();
+  std::shared_ptr<typename State::Client> client2 = state->createClient();
 
   // Make sure the expected events were logged
   uint32_t client2Id = checkNewConnEvents(log);
@@ -683,13 +683,13 @@
   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
-  const stdcxx::shared_ptr<EventLog>& log = state->getLog();
+  const std::shared_ptr<EventLog>& log = state->getLog();
 
   // Create a client
-  stdcxx::shared_ptr<typename State::Client> client = state->createClient();
+  std::shared_ptr<typename State::Client> client = state->createClient();
   uint32_t connId = checkNewConnEvents(log);
 
   // Make a oneway call
@@ -735,13 +735,13 @@
   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
-  const stdcxx::shared_ptr<EventLog>& log = state->getLog();
+  const std::shared_ptr<EventLog>& log = state->getLog();
 
   // Create a client
-  stdcxx::shared_ptr<typename State::Client> client = state->createClient();
+  std::shared_ptr<typename State::Client> client = state->createClient();
   uint32_t connId = checkNewConnEvents(log);
 
   // Send the exceptionWait() call
@@ -790,13 +790,13 @@
   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
 
   // Start the server
-  stdcxx::shared_ptr<State> state(new State);
+  std::shared_ptr<State> state(new State);
   ServerThread serverThread(state, true);
 
-  const stdcxx::shared_ptr<EventLog>& log = state->getLog();
+  const std::shared_ptr<EventLog>& log = state->getLog();
 
   // Create a client
-  stdcxx::shared_ptr<typename State::Client> client = state->createClient();
+  std::shared_ptr<typename State::Client> client = state->createClient();
   uint32_t connId = checkNewConnEvents(log);
 
   // Send the unexpectedExceptionWait() call
diff --git a/lib/cpp/test/processor/ServerThread.cpp b/lib/cpp/test/processor/ServerThread.cpp
index e752d5e..4d1ec4c 100644
--- a/lib/cpp/test/processor/ServerThread.cpp
+++ b/lib/cpp/test/processor/ServerThread.cpp
@@ -130,7 +130,7 @@
   serverState_->bindSuccessful(port_);
 
   // Set the real server event handler (replacing ourself)
-  stdcxx::shared_ptr<server::TServerEventHandler> serverEventHandler
+  std::shared_ptr<server::TServerEventHandler> serverEventHandler
       = serverState_->getServerEventHandler();
   server_->setServerEventHandler(serverEventHandler);
 
diff --git a/lib/cpp/test/processor/ServerThread.h b/lib/cpp/test/processor/ServerThread.h
index 21c3b60..61e31a3 100644
--- a/lib/cpp/test/processor/ServerThread.h
+++ b/lib/cpp/test/processor/ServerThread.h
@@ -43,7 +43,7 @@
    * If the server returned fails to bind to the specified port when serve() is
    * called on it, createServer() may be called again on a different port.
    */
-  virtual stdcxx::shared_ptr<server::TServer> createServer(uint16_t port) = 0;
+  virtual std::shared_ptr<server::TServer> createServer(uint16_t port) = 0;
 
   /**
    * Get the TServerEventHandler to set on the server.
@@ -52,8 +52,8 @@
    * start serving traffic.  It is invoked from the server thread, rather than
    * the main thread.
    */
-  virtual stdcxx::shared_ptr<server::TServerEventHandler> getServerEventHandler() {
-    return stdcxx::shared_ptr<server::TServerEventHandler>();
+  virtual std::shared_ptr<server::TServerEventHandler> getServerEventHandler() {
+    return std::shared_ptr<server::TServerEventHandler>();
   }
 
   /**
@@ -70,7 +70,7 @@
  */
 class ServerThread {
 public:
-  ServerThread(const stdcxx::shared_ptr<ServerState>& state, bool autoStart)
+  ServerThread(const std::shared_ptr<ServerState>& state, bool autoStart)
     : port_(0),
       running_(false),
       serving_(false),
@@ -116,7 +116,7 @@
   void run();
   void preServe();
 
-  stdcxx::shared_ptr<Helper> helper_;
+  std::shared_ptr<Helper> helper_;
 
   uint16_t port_;
   bool running_;
@@ -124,9 +124,9 @@
   bool error_;
   concurrency::Monitor serverMonitor_;
 
-  stdcxx::shared_ptr<ServerState> serverState_;
-  stdcxx::shared_ptr<server::TServer> server_;
-  stdcxx::shared_ptr<concurrency::Thread> thread_;
+  std::shared_ptr<ServerState> serverState_;
+  std::shared_ptr<server::TServer> server_;
+  std::shared_ptr<concurrency::Thread> thread_;
 };
 }
 }
diff --git a/lib/cpp/test/qt/TQTcpServerTest.cpp b/lib/cpp/test/qt/TQTcpServerTest.cpp
index 8a327aa..58d0c6d 100644
--- a/lib/cpp/test/qt/TQTcpServerTest.cpp
+++ b/lib/cpp/test/qt/TQTcpServerTest.cpp
@@ -8,7 +8,6 @@
 #include <QThread>
 
 #ifndef Q_MOC_RUN
-  #include "thrift/stdcxx.h"
   #include "thrift/protocol/TBinaryProtocol.h"
   #include "thrift/async/TAsyncProcessor.h"
   #include "thrift/qt/TQTcpServer.h"
@@ -21,25 +20,25 @@
 
 struct AsyncHandler : public test::ParentServiceCobSvIf {
   std::vector<std::string> strings;
-  virtual void addString(stdcxx::function<void()> cob, const std::string& s) {
+  virtual void addString(std::function<void()> cob, const std::string& s) {
     strings.push_back(s);
     cob();
   }
-  virtual void getStrings(stdcxx::function<void(std::vector<std::string> const& _return)> cob) {
+  virtual void getStrings(std::function<void(std::vector<std::string> const& _return)> cob) {
     cob(strings);
   }
 
   // Overrides not used in this test
-  virtual void incrementGeneration(stdcxx::function<void(int32_t const& _return)> cob) {}
-  virtual void getGeneration(stdcxx::function<void(int32_t const& _return)> cob) {}
-  virtual void getDataWait(stdcxx::function<void(std::string const& _return)> cob,
+  virtual void incrementGeneration(std::function<void(int32_t const& _return)> cob) {}
+  virtual void getGeneration(std::function<void(int32_t const& _return)> cob) {}
+  virtual void getDataWait(std::function<void(std::string const& _return)> cob,
                            const int32_t length) {}
-  virtual void onewayWait(stdcxx::function<void()> cob) {}
+  virtual void onewayWait(std::function<void()> cob) {}
   virtual void exceptionWait(
-      stdcxx::function<void()> cob,
-      stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */,
+      std::function<void()> cob,
+      std::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */,
       const std::string& message) {}
-  virtual void unexpectedExceptionWait(stdcxx::function<void()> cob, const std::string& message) {}
+  virtual void unexpectedExceptionWait(std::function<void()> cob, const std::string& message) {}
 };
 
 class TQTcpServerTest : public QObject {
@@ -51,18 +50,18 @@
   void test_communicate();
 
 private:
-  stdcxx::shared_ptr<QThread> serverThread;
-  stdcxx::shared_ptr<async::TQTcpServer> server;
-  stdcxx::shared_ptr<test::ParentServiceClient> client;
+  std::shared_ptr<QThread> serverThread;
+  std::shared_ptr<async::TQTcpServer> server;
+  std::shared_ptr<test::ParentServiceClient> client;
 };
 
 void TQTcpServerTest::initTestCase() {
   // setup server
-  stdcxx::shared_ptr<QTcpServer> serverSocket = stdcxx::make_shared<QTcpServer>();
+  std::shared_ptr<QTcpServer> serverSocket = std::make_shared<QTcpServer>();
   server.reset(new async::TQTcpServer(serverSocket,
-                                      stdcxx::make_shared<test::ParentServiceAsyncProcessor>(
-                                      stdcxx::make_shared<AsyncHandler>()),
-                                      stdcxx::make_shared<protocol::TBinaryProtocolFactory>()));
+                                      std::make_shared<test::ParentServiceAsyncProcessor>(
+                                      std::make_shared<AsyncHandler>()),
+                                      std::make_shared<protocol::TBinaryProtocolFactory>()));
   QVERIFY(serverSocket->listen(QHostAddress::LocalHost));
   int port = serverSocket->serverPort();
   QVERIFY(port > 0);
@@ -74,9 +73,9 @@
   serverThread->start();
 
   // setup client
-  stdcxx::shared_ptr<QTcpSocket> socket = stdcxx::make_shared<QTcpSocket>();
-  client.reset(new test::ParentServiceClient(stdcxx::make_shared<protocol::TBinaryProtocol>(
-      stdcxx::make_shared<transport::TQIODeviceTransport>(socket))));
+  std::shared_ptr<QTcpSocket> socket = std::make_shared<QTcpSocket>();
+  client.reset(new test::ParentServiceClient(std::make_shared<protocol::TBinaryProtocol>(
+      std::make_shared<transport::TQIODeviceTransport>(socket))));
   socket->connectToHost(QHostAddress::LocalHost, port);
   QVERIFY(socket->waitForConnected());
 }
diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am
index be49d5e..56a8b0f 100644
--- a/lib/csharp/Makefile.am
+++ b/lib/csharp/Makefile.am
@@ -109,3 +109,7 @@
 	test \
 	coding_standards.md \
 	README.md
+
+MAINTAINERCLEANFILES = \
+	Makefile \
+	Makefile.in
diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs
index 974cf27..c741b72 100644
--- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs
+++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs
@@ -56,5 +56,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.*")]
-[assembly: AssemblyFileVersion("0.11.0.*")]
+[assembly: AssemblyVersion("1.0.0.*")]
+[assembly: AssemblyFileVersion("1.0.0.*")]
diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj
index 1ee29d1..a319df2 100644
--- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj
+++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj
@@ -45,7 +45,7 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
@@ -115,4 +115,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
\ No newline at end of file
+</Project>
diff --git a/lib/csharp/src/Collections/TCollections.cs b/lib/csharp/src/Collections/TCollections.cs
index f0bb1de..84afb6a 100644
--- a/lib/csharp/src/Collections/TCollections.cs
+++ b/lib/csharp/src/Collections/TCollections.cs
@@ -79,7 +79,7 @@
             }
 
             int hashcode = 0;
-            foreach (Object obj in enumerable)
+            foreach (object obj in enumerable)
             {
                 IEnumerable enum2 = obj as IEnumerable;
                 int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2);
@@ -91,4 +91,4 @@
             return hashcode;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs
index ab6921e..7e86781 100644
--- a/lib/csharp/src/Properties/AssemblyInfo.cs
+++ b/lib/csharp/src/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 //
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
-[assembly: AssemblyVersion("0.11.0.1")]
-[assembly: AssemblyFileVersion("0.11.0.1")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/csharp/src/Protocol/TAbstractBase.cs b/lib/csharp/src/Protocol/TAbstractBase.cs
index c0d5abe..f5a61cd 100644
--- a/lib/csharp/src/Protocol/TAbstractBase.cs
+++ b/lib/csharp/src/Protocol/TAbstractBase.cs
@@ -21,9 +21,9 @@
 {
     public interface TAbstractBase
     {
-        ///
-        /// Writes the objects out to the protocol
-        ///
+        /// <summary>
+        /// Writes the objects out to the protocol.
+        /// </summary>
         void Write(TProtocol tProtocol);
     }
 }
diff --git a/lib/csharp/src/Protocol/TBase.cs b/lib/csharp/src/Protocol/TBase.cs
index 350ff49..411e4d9 100644
--- a/lib/csharp/src/Protocol/TBase.cs
+++ b/lib/csharp/src/Protocol/TBase.cs
@@ -21,9 +21,9 @@
 {
     public interface TBase : TAbstractBase
     {
-        ///
+        /// <summary>
         /// Reads the TObject from the given input protocol.
-        ///
+        /// </summary>
         void Read(TProtocol tProtocol);
     }
 }
diff --git a/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs
index 4eceb86..a4faa94 100644
--- a/lib/csharp/src/Protocol/TBinaryProtocol.cs
+++ b/lib/csharp/src/Protocol/TBinaryProtocol.cs
@@ -36,29 +36,28 @@
         protected bool strictWrite_ = true;
 
         #region BinaryProtocol Factory
-         /**
-          * Factory
-          */
-          public class Factory : TProtocolFactory {
 
-              protected bool strictRead_ = false;
-              protected bool strictWrite_ = true;
+        public class Factory : TProtocolFactory
+        {
+            protected bool strictRead_ = false;
+            protected bool strictWrite_ = true;
 
-              public Factory()
-                  :this(false, true)
-              {
-              }
-
-              public Factory(bool strictRead, bool strictWrite)
-              {
-                  strictRead_ = strictRead;
-                  strictWrite_ = strictWrite;
-              }
-
-            public TProtocol GetProtocol(TTransport trans) {
-              return new TBinaryProtocol(trans, strictRead_, strictWrite_);
+            public Factory()
+                : this(false, true)
+            {
             }
-          }
+
+            public Factory(bool strictRead, bool strictWrite)
+            {
+                strictRead_ = strictRead;
+                strictWrite_ = strictWrite;
+            }
+
+            public TProtocol GetProtocol(TTransport trans)
+            {
+                return new TBinaryProtocol(trans, strictRead_, strictWrite_);
+            }
+        }
 
         #endregion
 
@@ -68,7 +67,7 @@
         }
 
         public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
-            :base(trans)
+            : base(trans)
         {
             strictRead_ = strictRead;
             strictWrite_ = strictWrite;
@@ -345,16 +344,17 @@
         public override long ReadI64()
         {
             ReadAll(i64in, 0, 8);
-            unchecked {
-              return (long)(
-                  ((long)(i64in[0] & 0xff) << 56) |
-                  ((long)(i64in[1] & 0xff) << 48) |
-                  ((long)(i64in[2] & 0xff) << 40) |
-                  ((long)(i64in[3] & 0xff) << 32) |
-                  ((long)(i64in[4] & 0xff) << 24) |
-                  ((long)(i64in[5] & 0xff) << 16) |
-                  ((long)(i64in[6] & 0xff) << 8) |
-                  ((long)(i64in[7] & 0xff)));
+            unchecked
+            {
+                return (long)(
+                    ((long)(i64in[0] & 0xff) << 56) |
+                    ((long)(i64in[1] & 0xff) << 48) |
+                    ((long)(i64in[2] & 0xff) << 40) |
+                    ((long)(i64in[3] & 0xff) << 32) |
+                    ((long)(i64in[4] & 0xff) << 24) |
+                    ((long)(i64in[5] & 0xff) << 16) |
+                    ((long)(i64in[6] & 0xff) << 8) |
+                    ((long)(i64in[7] & 0xff)));
             }
         }
 
@@ -378,7 +378,7 @@
             trans.ReadAll(buf, 0, size);
             return buf;
         }
-        private  string ReadStringBody(int size)
+        private string ReadStringBody(int size)
         {
             byte[] buf = new byte[size];
             trans.ReadAll(buf, 0, size);
diff --git a/lib/csharp/src/Protocol/TCompactProtocol.cs b/lib/csharp/src/Protocol/TCompactProtocol.cs
index 2b4f6f1..ff67397 100644
--- a/lib/csharp/src/Protocol/TCompactProtocol.cs
+++ b/lib/csharp/src/Protocol/TCompactProtocol.cs
@@ -44,9 +44,9 @@
         private const byte TYPE_BITS = 0x07; // 0000 0111
         private const int TYPE_SHIFT_AMOUNT = 5;
 
-        /**
-         * All of the on-wire type codes.
-         */
+        /// <summary>
+        /// All of the on-wire type codes.
+        /// </summary>
         private static class Types
         {
             public const byte STOP = 0x00;
@@ -64,32 +64,29 @@
             public const byte STRUCT = 0x0C;
         }
 
-        /**
-         * Used to keep track of the last field for the current and previous structs,
-         * so we can do the delta stuff.
-         */
+        /// <summary>
+        /// Used to keep track of the last field for the current and previous structs,
+        /// so we can do the delta stuff.
+        /// </summary>
         private Stack<short> lastField_ = new Stack<short>(15);
 
         private short lastFieldId_ = 0;
 
-        /**
-         * If we encounter a boolean field begin, save the TField here so it can
-         * have the value incorporated.
-         */
+        /// <summary>
+        /// If we encounter a boolean field begin, save the TField here so it can
+        /// have the value incorporated.
+        /// </summary>
         private Nullable<TField> booleanField_;
 
-        /**
-         * If we Read a field header, and it's a boolean field, save the boolean
-         * value here so that ReadBool can use it.
-         */
-        private  Nullable<Boolean> boolValue_;
+        /// <summary>
+        /// If we Read a field header, and it's a boolean field, save the boolean
+        /// value here so that ReadBool can use it.
+        /// </summary>
+        private Nullable<Boolean> boolValue_;
 
 
         #region CompactProtocol Factory
 
-        /**
-          * Factory
-          */
         public class Factory : TProtocolFactory
         {
             public Factory() { }
@@ -127,31 +124,32 @@
 
         #region Write Methods
 
-
-        /**
-         * Writes a byte without any possibility of all that field header nonsense.
-         * Used internally by other writing methods that know they need to Write a byte.
-         */
+        /// <summary>
+        /// Writes a byte without any possibility of all that field header nonsense.
+        /// Used internally by other writing methods that know they need to Write a byte.
+        /// </summary>
         private byte[] byteDirectBuffer = new byte[1];
+
         private void WriteByteDirect(byte b)
         {
             byteDirectBuffer[0] = b;
             trans.Write(byteDirectBuffer);
         }
 
-        /**
-         * Writes a byte without any possibility of all that field header nonsense.
-         */
+        /// <summary>
+        /// Writes a byte without any possibility of all that field header nonsense.
+        /// </summary>
         private void WriteByteDirect(int n)
         {
             WriteByteDirect((byte)n);
         }
 
-        /**
-         * Write an i32 as a varint. Results in 1-5 bytes on the wire.
-         * TODO: make a permanent buffer like WriteVarint64?
-         */
+        /// <summary>
+        /// Write an i32 as a varint. Results in 1-5 bytes on the wire.
+        /// TODO: make a permanent buffer like WriteVarint64?
+        /// </summary>
         byte[] i32buf = new byte[5];
+
         private void WriteVarint32(uint n)
         {
             int idx = 0;
@@ -174,10 +172,10 @@
             trans.Write(i32buf, 0, idx);
         }
 
-        /**
-        * Write a message header to the wire. Compact Protocol messages contain the
-        * protocol version so we can migrate forwards in the future if need be.
-        */
+        /// <summary>
+        /// Write a message header to the wire. Compact Protocol messages contain the
+        /// protocol version so we can migrate forwards in the future if need be.
+        /// </summary>
         public override void WriteMessageBegin(TMessage message)
         {
             WriteByteDirect(PROTOCOL_ID);
@@ -186,33 +184,33 @@
             WriteString(message.Name);
         }
 
-        /**
-         * Write a struct begin. This doesn't actually put anything on the wire. We
-         * use it as an opportunity to put special placeholder markers on the field
-         * stack so we can get the field id deltas correct.
-         */
+        /// <summary>
+        /// Write a struct begin. This doesn't actually put anything on the wire. We
+        /// use it as an opportunity to put special placeholder markers on the field
+        /// stack so we can get the field id deltas correct.
+        /// </summary>
         public override void WriteStructBegin(TStruct strct)
         {
             lastField_.Push(lastFieldId_);
             lastFieldId_ = 0;
         }
 
-        /**
-         * Write a struct end. This doesn't actually put anything on the wire. We use
-         * this as an opportunity to pop the last field from the current struct off
-         * of the field stack.
-         */
+        /// <summary>
+        /// Write a struct end. This doesn't actually put anything on the wire. We use
+        /// this as an opportunity to pop the last field from the current struct off
+        /// of the field stack.
+        /// </summary>
         public override void WriteStructEnd()
         {
             lastFieldId_ = lastField_.Pop();
         }
 
-        /**
-         * Write a field header containing the field id and field type. If the
-         * difference between the current field id and the last one is small (< 15),
-         * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
-         * field id will follow the type header as a zigzag varint.
-         */
+        /// <summary>
+        /// Write a field header containing the field id and field type. If the
+        /// difference between the current field id and the last one is small (&lt; 15),
+        /// then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
+        /// field id will follow the type header as a zigzag varint.
+        /// </summary>
         public override void WriteFieldBegin(TField field)
         {
             if (field.Type == TType.Bool)
@@ -226,11 +224,11 @@
             }
         }
 
-        /**
-         * The workhorse of WriteFieldBegin. It has the option of doing a
-         * 'type override' of the type header. This is used specifically in the
-         * boolean field case.
-         */
+        /// <summary>
+        /// The workhorse of WriteFieldBegin. It has the option of doing a
+        /// 'type override' of the type header. This is used specifically in the
+        /// boolean field case.
+        /// </summary>
         private void WriteFieldBeginInternal(TField field, byte typeOverride)
         {
             // short lastField = lastField_.Pop();
@@ -255,18 +253,18 @@
             // lastField_.push(field.id);
         }
 
-        /**
-         * Write the STOP symbol so we know there are no more fields in this struct.
-         */
+        /// <summary>
+        /// Write the STOP symbol so we know there are no more fields in this struct.
+        /// </summary>
         public override void WriteFieldStop()
         {
             WriteByteDirect(Types.STOP);
         }
 
-        /**
-         * Write a map header. If the map is empty, omit the key and value type
-         * headers, as we don't need any additional information to skip it.
-         */
+        /// <summary>
+        /// Write a map header. If the map is empty, omit the key and value type
+        /// headers, as we don't need any additional information to skip it.
+        /// </summary>
         public override void WriteMapBegin(TMap map)
         {
             if (map.Count == 0)
@@ -280,28 +278,28 @@
             }
         }
 
-        /**
-         * Write a list header.
-         */
+        /// <summary>
+        /// Write a list header.
+        /// </summary>
         public override void WriteListBegin(TList list)
         {
             WriteCollectionBegin(list.ElementType, list.Count);
         }
 
-        /**
-         * Write a set header.
-         */
+        /// <summary>
+        /// Write a set header.
+        /// </summary>
         public override void WriteSetBegin(TSet set)
         {
             WriteCollectionBegin(set.ElementType, set.Count);
         }
 
-        /**
-         * Write a boolean value. Potentially, this could be a boolean field, in
-         * which case the field header info isn't written yet. If so, decide what the
-         * right type header is for the value and then Write the field header.
-         * Otherwise, Write a single byte.
-         */
+        /// <summary>
+        /// Write a boolean value. Potentially, this could be a boolean field, in
+        /// which case the field header info isn't written yet. If so, decide what the
+        /// right type header is for the value and then Write the field header.
+        /// Otherwise, Write a single byte.
+        /// </summary>
         public override void WriteBool(Boolean b)
         {
             if (booleanField_ != null)
@@ -317,41 +315,41 @@
             }
         }
 
-        /**
-         * Write a byte. Nothing to see here!
-         */
+        /// <summary>
+        /// Write a byte. Nothing to see here!
+        /// </summary>
         public override void WriteByte(sbyte b)
         {
             WriteByteDirect((byte)b);
         }
 
-        /**
-         * Write an I16 as a zigzag varint.
-         */
+        /// <summary>
+        /// Write an I16 as a zigzag varint.
+        /// </summary>
         public override void WriteI16(short i16)
         {
             WriteVarint32(intToZigZag(i16));
         }
 
-        /**
-         * Write an i32 as a zigzag varint.
-         */
+        /// <summary>
+        /// Write an i32 as a zigzag varint.
+        /// </summary>
         public override void WriteI32(int i32)
         {
             WriteVarint32(intToZigZag(i32));
         }
 
-        /**
-         * Write an i64 as a zigzag varint.
-         */
+        /// <summary>
+        /// Write an i64 as a zigzag varint.
+        /// </summary>
         public override void WriteI64(long i64)
         {
             WriteVarint64(longToZigzag(i64));
         }
 
-        /**
-         * Write a double to the wire as 8 bytes.
-         */
+        /// <summary>
+        /// Write a double to the wire as 8 bytes.
+        /// </summary>
         public override void WriteDouble(double dub)
         {
             byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -359,18 +357,18 @@
             trans.Write(data);
         }
 
-        /**
-         * Write a string to the wire with a varint size preceding.
-         */
-        public override void WriteString(String str)
+        /// <summary>
+        /// Write a string to the wire with a varint size preceding.
+        /// </summary>
+        public override void WriteString(string str)
         {
             byte[] bytes = UTF8Encoding.UTF8.GetBytes(str);
             WriteBinary(bytes, 0, bytes.Length);
         }
 
-        /**
-         * Write a byte array, using a varint for the size.
-         */
+        /// <summary>
+        /// Write a byte array, using a varint for the size.
+        /// </summary>
         public override void WriteBinary(byte[] bin)
         {
             WriteBinary(bin, 0, bin.Length);
@@ -397,10 +395,10 @@
         // Internal writing methods
         //
 
-        /**
-         * Abstract method for writing the start of lists and sets. List and sets on
-         * the wire differ only by the type indicator.
-         */
+        /// <summary>
+        /// Abstract method for writing the start of lists and sets. List and sets on
+        /// the wire differ only by the type indicator.
+        /// </summary>
         protected void WriteCollectionBegin(TType elemType, int size)
         {
             if (size <= 14)
@@ -414,9 +412,9 @@
             }
         }
 
-        /**
-         * Write an i64 as a varint. Results in 1-10 bytes on the wire.
-         */
+        /// <summary>
+        /// Write an i64 as a varint. Results in 1-10 bytes on the wire.
+        /// </summary>
         byte[] varint64out = new byte[10];
         private void WriteVarint64(ulong n)
         {
@@ -437,28 +435,28 @@
             trans.Write(varint64out, 0, idx);
         }
 
-        /**
-         * Convert l into a zigzag long. This allows negative numbers to be
-         * represented compactly as a varint.
-         */
+        /// <summary>
+        /// Convert l into a zigzag long. This allows negative numbers to be
+        /// represented compactly as a varint.
+        /// </summary>
         private ulong longToZigzag(long n)
         {
             return (ulong)(n << 1) ^ (ulong)(n >> 63);
         }
 
-        /**
-         * Convert n into a zigzag int. This allows negative numbers to be
-         * represented compactly as a varint.
-         */
+        /// <summary>
+        /// Convert n into a zigzag int. This allows negative numbers to be
+        /// represented compactly as a varint.
+        /// </summary>
         private uint intToZigZag(int n)
         {
             return (uint)(n << 1) ^ (uint)(n >> 31);
         }
 
-        /**
-         * Convert a long into little-endian bytes in buf starting at off and going
-         * until off+7.
-         */
+        /// <summary>
+        /// Convert a long into little-endian bytes in buf starting at off and going
+        /// until off+7.
+        /// </summary>
         private void fixedLongToBytes(long n, byte[] buf, int off)
         {
             buf[off + 0] = (byte)(n & 0xff);
@@ -475,9 +473,9 @@
 
         #region ReadMethods
 
-        /**
-   * Read a message header.
-   */
+        /// <summary>
+        /// Read a message header.
+        /// </summary>
         public override TMessage ReadMessageBegin()
         {
             byte protocolId = (byte)ReadByte();
@@ -493,14 +491,14 @@
             }
             byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
             int seqid = (int)ReadVarint32();
-            String messageName = ReadString();
+            string messageName = ReadString();
             return new TMessage(messageName, (TMessageType)type, seqid);
         }
 
-        /**
-         * Read a struct begin. There's nothing on the wire for this, but it is our
-         * opportunity to push a new struct begin marker onto the field stack.
-         */
+        /// <summary>
+        /// Read a struct begin. There's nothing on the wire for this, but it is our
+        /// opportunity to push a new struct begin marker onto the field stack.
+        /// </summary>
         public override TStruct ReadStructBegin()
         {
             lastField_.Push(lastFieldId_);
@@ -508,19 +506,19 @@
             return ANONYMOUS_STRUCT;
         }
 
-        /**
-         * Doesn't actually consume any wire data, just removes the last field for
-         * this struct from the field stack.
-         */
+        /// <summary>
+        /// Doesn't actually consume any wire data, just removes the last field for
+        /// this struct from the field stack.
+        /// </summary>
         public override void ReadStructEnd()
         {
             // consume the last field we Read off the wire.
             lastFieldId_ = lastField_.Pop();
         }
 
-        /**
-         * Read a field header off the wire.
-         */
+        /// <summary>
+        /// Read a field header off the wire.
+        /// </summary>
         public override TField ReadFieldBegin()
         {
             byte type = (byte)ReadByte();
@@ -560,11 +558,11 @@
             return field;
         }
 
-        /**
-         * Read a map header off the wire. If the size is zero, skip Reading the key
-         * and value type. This means that 0-length maps will yield TMaps without the
-         * "correct" types.
-         */
+        /// <summary>
+        /// Read a map header off the wire. If the size is zero, skip Reading the key
+        /// and value type. This means that 0-length maps will yield TMaps without the
+        /// "correct" types.
+        /// </summary>
         public override TMap ReadMapBegin()
         {
             int size = (int)ReadVarint32();
@@ -572,12 +570,12 @@
             return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size);
         }
 
-        /**
-         * Read a list header off the wire. If the list size is 0-14, the size will
-         * be packed into the element type header. If it's a longer list, the 4 MSB
-         * of the element type header will be 0xF, and a varint will follow with the
-         * true size.
-         */
+        /// <summary>
+        /// Read a list header off the wire. If the list size is 0-14, the size will
+        /// be packed into the element type header. If it's a longer list, the 4 MSB
+        /// of the element type header will be 0xF, and a varint will follow with the
+        /// true size.
+        /// </summary>
         public override TList ReadListBegin()
         {
             byte size_and_type = (byte)ReadByte();
@@ -590,22 +588,22 @@
             return new TList(type, size);
         }
 
-        /**
-         * Read a set header off the wire. If the set size is 0-14, the size will
-         * be packed into the element type header. If it's a longer set, the 4 MSB
-         * of the element type header will be 0xF, and a varint will follow with the
-         * true size.
-         */
+        /// <summary>
+        /// Read a set header off the wire. If the set size is 0-14, the size will
+        /// be packed into the element type header. If it's a longer set, the 4 MSB
+        /// of the element type header will be 0xF, and a varint will follow with the
+        /// true size.
+        /// </summary>
         public override TSet ReadSetBegin()
         {
             return new TSet(ReadListBegin());
         }
 
-        /**
-         * Read a boolean off the wire. If this is a boolean field, the value should
-         * already have been Read during ReadFieldBegin, so we'll just consume the
-         * pre-stored value. Otherwise, Read a byte.
-         */
+        /// <summary>
+        /// Read a boolean off the wire. If this is a boolean field, the value should
+        /// already have been Read during ReadFieldBegin, so we'll just consume the
+        /// pre-stored value. Otherwise, Read a byte.
+        /// </summary>
         public override Boolean ReadBool()
         {
             if (boolValue_ != null)
@@ -618,42 +616,42 @@
         }
 
         byte[] byteRawBuf = new byte[1];
-        /**
-         * Read a single byte off the wire. Nothing interesting here.
-         */
+        /// <summary>
+        /// Read a single byte off the wire. Nothing interesting here.
+        /// </summary>
         public override sbyte ReadByte()
         {
             trans.ReadAll(byteRawBuf, 0, 1);
             return (sbyte)byteRawBuf[0];
         }
 
-        /**
-         * Read an i16 from the wire as a zigzag varint.
-         */
+        /// <summary>
+        /// Read an i16 from the wire as a zigzag varint.
+        /// </summary>
         public override short ReadI16()
         {
             return (short)zigzagToInt(ReadVarint32());
         }
 
-        /**
-         * Read an i32 from the wire as a zigzag varint.
-         */
+        /// <summary>
+        /// Read an i32 from the wire as a zigzag varint.
+        /// </summary>
         public override int ReadI32()
         {
             return zigzagToInt(ReadVarint32());
         }
 
-        /**
-         * Read an i64 from the wire as a zigzag varint.
-         */
+        /// <summary>
+        /// Read an i64 from the wire as a zigzag varint.
+        /// </summary>
         public override long ReadI64()
         {
             return zigzagToLong(ReadVarint64());
         }
 
-        /**
-         * No magic here - just Read a double off the wire.
-         */
+        /// <summary>
+        /// No magic here - just Read a double off the wire.
+        /// </summary>
         public override double ReadDouble()
         {
             byte[] longBits = new byte[8];
@@ -661,10 +659,10 @@
             return BitConverter.Int64BitsToDouble(bytesToLong(longBits));
         }
 
-        /**
-         * Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
-         */
-        public override String ReadString()
+        /// <summary>
+        /// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
+        /// </summary>
+        public override string ReadString()
         {
             int length = (int)ReadVarint32();
 
@@ -676,9 +674,9 @@
             return Encoding.UTF8.GetString(ReadBinary(length));
         }
 
-        /**
-         * Read a byte[] from the wire.
-         */
+        /// <summary>
+        /// Read a byte[] from the wire.
+        /// </summary>
         public override byte[] ReadBinary()
         {
             int length = (int)ReadVarint32();
@@ -689,9 +687,9 @@
             return buf;
         }
 
-        /**
-         * Read a byte[] of a known length from the wire.
-         */
+        /// <summary>
+        /// Read a byte[] of a known length from the wire.
+        /// </summary>
         private byte[] ReadBinary(int length)
         {
             if (length == 0) return new byte[0];
@@ -715,10 +713,10 @@
         // Internal Reading methods
         //
 
-        /**
-         * Read an i32 from the wire as a varint. The MSB of each byte is set
-         * if there is another byte to follow. This can Read up to 5 bytes.
-         */
+        /// <summary>
+        /// Read an i32 from the wire as a varint. The MSB of each byte is set
+        /// if there is another byte to follow. This can Read up to 5 bytes.
+        /// </summary>
         private uint ReadVarint32()
         {
             uint result = 0;
@@ -733,10 +731,10 @@
             return result;
         }
 
-        /**
-         * Read an i64 from the wire as a proper varint. The MSB of each byte is set
-         * if there is another byte to follow. This can Read up to 10 bytes.
-         */
+        /// <summary>
+        /// Read an i64 from the wire as a proper varint. The MSB of each byte is set
+        /// if there is another byte to follow. This can Read up to 10 bytes.
+        /// </summary>
         private ulong ReadVarint64()
         {
             int shift = 0;
@@ -758,27 +756,27 @@
         // encoding helpers
         //
 
-        /**
-         * Convert from zigzag int to int.
-         */
+        /// <summary>
+        /// Convert from zigzag int to int.
+        /// </summary>
         private int zigzagToInt(uint n)
         {
             return (int)(n >> 1) ^ (-(int)(n & 1));
         }
 
-        /**
-         * Convert from zigzag long to long.
-         */
+        /// <summary>
+        /// Convert from zigzag long to long.
+        /// </summary>
         private long zigzagToLong(ulong n)
         {
             return (long)(n >> 1) ^ (-(long)(n & 1));
         }
 
-        /**
-         * Note that it's important that the mask bytes are long literals,
-         * otherwise they'll default to ints, and when you shift an int left 56 bits,
-         * you just get a messed up int.
-         */
+        /// <summary>
+        /// Note that it's important that the mask bytes are long literals,
+        /// otherwise they'll default to ints, and when you shift an int left 56 bits,
+        /// you just get a messed up int.
+        /// </summary>
         private long bytesToLong(byte[] bytes)
         {
             return
@@ -802,10 +800,10 @@
             return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE;
         }
 
-        /**
-         * Given a TCompactProtocol.Types constant, convert it to its corresponding
-         * TType value.
-         */
+        /// <summary>
+        /// Given a TCompactProtocol.Types constant, convert it to its corresponding
+        /// TType value.
+        /// </summary>
         private TType getTType(byte type)
         {
             switch ((byte)(type & 0x0f))
@@ -840,9 +838,9 @@
             }
         }
 
-        /**
-         * Given a TType value, find the appropriate TCompactProtocol.Types constant.
-         */
+        /// <summary>
+        /// Given a TType value, find the appropriate TCompactProtocol.Types constant.
+        /// </summary>
         private byte getCompactType(TType ttype)
         {
             return ttypeToCompactType[(int)ttype];
diff --git a/lib/csharp/src/Protocol/TJSONProtocol.cs b/lib/csharp/src/Protocol/TJSONProtocol.cs
index 5e6589e..9dbdea9 100644
--- a/lib/csharp/src/Protocol/TJSONProtocol.cs
+++ b/lib/csharp/src/Protocol/TJSONProtocol.cs
@@ -29,18 +29,18 @@
 {
     /// <summary>
     /// JSON protocol implementation for thrift.
-    ///
+    /// <para/>
     /// This is a full-featured protocol supporting Write and Read.
-    ///
+    /// <para/>
     /// Please see the C++ class header for a detailed description of the
     /// protocol's wire format.
-    ///
+    /// <para/>
     /// Adapted from the Java version.
     /// </summary>
     public class TJSONProtocol : TProtocol
     {
         /// <summary>
-        /// Factory for JSON protocol objects
+        /// Factory for JSON protocol objects.
         /// </summary>
         public class Factory : TProtocolFactory
         {
@@ -179,11 +179,11 @@
             return result;
         }
 
-        ///<summary>
+        /// <summary>
         /// Base class for tracking JSON contexts that may require
         /// inserting/Reading additional JSON syntax characters
         /// This base context does nothing.
-        ///</summary>
+        /// </summary>
         protected class JSONBaseContext
         {
             protected TJSONProtocol proto;
@@ -200,10 +200,10 @@
             public virtual bool EscapeNumbers() { return false; }
         }
 
-        ///<summary>
+        /// <summary>
         /// Context for JSON lists. Will insert/Read commas before each item except
         /// for the first one
-        ///</summary>
+        /// </summary>
         protected class JSONListContext : JSONBaseContext
         {
             public JSONListContext(TJSONProtocol protocol)
@@ -239,12 +239,12 @@
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Context for JSON records. Will insert/Read colons before the value portion
         /// of each record pair, and commas before each key except the first. In
         /// addition, will indicate that numbers in the key position need to be
         /// escaped in quotes (since JSON keys must be strings).
-        ///</summary>
+        /// </summary>
         protected class JSONPairContext : JSONBaseContext
         {
             public JSONPairContext(TJSONProtocol proto)
@@ -290,9 +290,9 @@
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Holds up to one byte from the transport
-        ///</summary>
+        /// </summary>
         protected class LookaheadReader
         {
             protected TJSONProtocol proto;
@@ -305,10 +305,10 @@
             private bool hasData;
             private byte[] data = new byte[1];
 
-            ///<summary>
+            /// <summary>
             /// Return and consume the next byte to be Read, either taking it from the
             /// data buffer if present or getting it from the transport otherwise.
-            ///</summary>
+            /// </summary>
             public byte Read()
             {
                 if (hasData)
@@ -322,10 +322,10 @@
                 return data[0];
             }
 
-            ///<summary>
+            /// <summary>
             /// Return the next byte to be Read without consuming, filling the data
             /// buffer if it has not been filled alReady.
-            ///</summary>
+            /// </summary>
             public byte Peek()
             {
                 if (!hasData)
@@ -349,26 +349,26 @@
         // Reader that manages a 1-byte buffer
         protected LookaheadReader reader;
 
-        ///<summary>
+        /// <summary>
         /// Push a new JSON context onto the stack.
-        ///</summary>
+        /// </summary>
         protected void PushContext(JSONBaseContext c)
         {
             contextStack.Push(context);
             context = c;
         }
 
-        ///<summary>
+        /// <summary>
         /// Pop the last JSON context off the stack
-        ///</summary>
+        /// </summary>
         protected void PopContext()
         {
             context = contextStack.Pop();
         }
 
-        ///<summary>
+        /// <summary>
         /// TJSONProtocol Constructor
-        ///</summary>
+        /// </summary>
         public TJSONProtocol(TTransport trans)
             : base(trans)
         {
@@ -379,11 +379,11 @@
         // Temporary buffer used by several methods
         private byte[] tempBuffer = new byte[4];
 
-        ///<summary>
+        /// <summary>
         /// Read a byte that must match b[0]; otherwise an exception is thrown.
         /// Marked protected to avoid synthetic accessor in JSONListContext.Read
         /// and JSONPairContext.Read
-        ///</summary>
+        /// </summary>
         protected void ReadJSONSyntaxChar(byte[] b)
         {
             byte ch = reader.Read();
@@ -394,10 +394,10 @@
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
         /// corresponding hex value
-        ///</summary>
+        /// </summary>
         private static byte HexVal(byte ch)
         {
             if ((ch >= '0') && (ch <= '9'))
@@ -416,9 +416,9 @@
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Convert a byte containing a hex value to its corresponding hex character
-        ///</summary>
+        /// </summary>
         private static byte HexChar(byte val)
         {
             val &= 0x0F;
@@ -433,9 +433,9 @@
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Write the bytes in array buf as a JSON characters, escaping as needed
-        ///</summary>
+        /// </summary>
         private void WriteJSONString(byte[] b)
         {
             context.Write();
@@ -479,14 +479,14 @@
             trans.Write(QUOTE);
         }
 
-        ///<summary>
+        /// <summary>
         /// Write out number as a JSON value. If the context dictates so, it will be
         /// wrapped in quotes to output as a JSON string.
-        ///</summary>
+        /// </summary>
         private void WriteJSONInteger(long num)
         {
             context.Write();
-            String str = num.ToString();
+            string str = num.ToString();
 
             bool escapeNum = context.EscapeNumbers();
             if (escapeNum)
@@ -498,14 +498,14 @@
                 trans.Write(QUOTE);
         }
 
-        ///<summary>
+        /// <summary>
         /// Write out a double as a JSON value. If it is NaN or infinity or if the
         /// context dictates escaping, Write out as JSON string.
-        ///</summary>
+        /// </summary>
         private void WriteJSONDouble(double num)
         {
             context.Write();
-            String str = num.ToString("G17", CultureInfo.InvariantCulture);
+            string str = num.ToString("G17", CultureInfo.InvariantCulture);
             bool special = false;
 
             switch (str[0])
@@ -532,10 +532,10 @@
             if (escapeNum)
                 trans.Write(QUOTE);
         }
-        ///<summary>
+        /// <summary>
         /// Write out contents of byte array b as a JSON string with base-64 encoded
         /// data
-        ///</summary>
+        /// </summary>
         private void WriteJSONBase64(byte[] b)
         {
             context.Write();
@@ -544,11 +544,6 @@
             int len = b.Length;
             int off = 0;
 
-            // Ignore padding
-            int bound = len >= 2 ? len - 2 : 0;
-            for (int i = len - 1; i >= bound && b[i] == '='; --i) {
-                --len;
-            }
             while (len >= 3)
             {
                 // Encode 3 bytes at a time
@@ -703,7 +698,7 @@
             WriteJSONDouble(dub);
         }
 
-        public override void WriteString(String str)
+        public override void WriteString(string str)
         {
             byte[] b = utf8Encoding.GetBytes(str);
             WriteJSONString(b);
@@ -718,10 +713,10 @@
          * Reading methods.
          */
 
-        ///<summary>
+        /// <summary>
         /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the
         /// context if skipContext is true.
-        ///</summary>
+        /// </summary>
         private byte[] ReadJSONString(bool skipContext)
         {
             MemoryStream buffer = new MemoryStream();
@@ -808,9 +803,9 @@
             return buffer.ToArray();
         }
 
-        ///<summary>
+        /// <summary>
         /// Return true if the given byte could be a valid part of a JSON number.
-        ///</summary>
+        /// </summary>
         private bool IsJSONNumeric(byte b)
         {
             switch (b)
@@ -835,11 +830,11 @@
             return false;
         }
 
-        ///<summary>
+        /// <summary>
         /// Read in a sequence of characters that are all valid in JSON numbers. Does
         /// not do a complete regex check to validate that this is actually a number.
-        ////</summary>
-        private String ReadJSONNumericChars()
+        /// </summary>
+        private string ReadJSONNumericChars()
         {
             StringBuilder strbld = new StringBuilder();
             while (true)
@@ -854,9 +849,9 @@
             return strbld.ToString();
         }
 
-        ///<summary>
+        /// <summary>
         /// Read in a JSON number. If the context dictates, Read in enclosing quotes.
-        ///</summary>
+        /// </summary>
         private long ReadJSONInteger()
         {
             context.Read();
@@ -864,36 +859,37 @@
             {
                 ReadJSONSyntaxChar(QUOTE);
             }
-            String str = ReadJSONNumericChars();
+
+            string str = ReadJSONNumericChars();
             if (context.EscapeNumbers())
             {
                 ReadJSONSyntaxChar(QUOTE);
             }
+
             try
             {
                 return Int64.Parse(str);
             }
-            catch (FormatException)
+            catch (FormatException fex)
             {
                 throw new TProtocolException(TProtocolException.INVALID_DATA,
-                                             "Bad data encounted in numeric data");
+                                             "Bad data encounted in numeric data", fex);
             }
         }
 
-        ///<summary>
+        /// <summary>
         /// Read in a JSON double value. Throw if the value is not wrapped in quotes
         /// when expected or if wrapped in quotes when not expected.
-        ///</summary>
+        /// </summary>
         private double ReadJSONDouble()
         {
             context.Read();
             if (reader.Peek() == QUOTE[0])
             {
                 byte[] arr = ReadJSONString(true);
-                double dub = Double.Parse(utf8Encoding.GetString(arr,0,arr.Length), CultureInfo.InvariantCulture);
+                double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
 
-                if (!context.EscapeNumbers() && !Double.IsNaN(dub) &&
-                    !Double.IsInfinity(dub))
+                if (!context.EscapeNumbers() && !Double.IsNaN(dub) && !Double.IsInfinity(dub))
                 {
                     // Throw exception -- we should not be in a string in this case
                     throw new TProtocolException(TProtocolException.INVALID_DATA,
@@ -912,17 +908,17 @@
                 {
                     return Double.Parse(ReadJSONNumericChars(), CultureInfo.InvariantCulture);
                 }
-                catch (FormatException)
+                catch (FormatException fex)
                 {
                     throw new TProtocolException(TProtocolException.INVALID_DATA,
-                                                 "Bad data encounted in numeric data");
+                                                 "Bad data encounted in numeric data", fex);
                 }
             }
         }
 
-        //<summary>
+        /// <summary>
         /// Read in a JSON string containing base-64 encoded data and decode it.
-        ///</summary>
+        /// </summary>
         private byte[] ReadJSONBase64()
         {
             byte[] b = ReadJSONString(false);
@@ -994,7 +990,7 @@
             }
 
             var buf = ReadJSONString(false);
-            message.Name = utf8Encoding.GetString(buf,0,buf.Length);
+            message.Name = utf8Encoding.GetString(buf, 0, buf.Length);
             message.Type = (TMessageType)ReadJSONInteger();
             message.SeqID = (int)ReadJSONInteger();
             return message;
@@ -1113,10 +1109,10 @@
             return ReadJSONDouble();
         }
 
-        public override String ReadString()
+        public override string ReadString()
         {
             var buf = ReadJSONString(false);
-            return utf8Encoding.GetString(buf,0,buf.Length);
+            return utf8Encoding.GetString(buf, 0, buf.Length);
         }
 
         public override byte[] ReadBinary()
diff --git a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
index 35d138c..aa91c52 100644
--- a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
+++ b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
@@ -29,74 +29,77 @@
 
 namespace Thrift.Protocol
 {
-
-    /**
-     * TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services.
-     * To do so, you instantiate the processor and then register additional processors with it,
-     * as shown in the following example:
-     *
-     *     TMultiplexedProcessor processor = new TMultiplexedProcessor();
-     *
-     *     processor.registerProcessor(
-     *         "Calculator",
-     *         new Calculator.Processor(new CalculatorHandler()));
-     *
-     *     processor.registerProcessor(
-     *         "WeatherReport",
-     *         new WeatherReport.Processor(new WeatherReportHandler()));
-     *
-     *     TServerTransport t = new TServerSocket(9090);
-     *     TSimpleServer server = new TSimpleServer(processor, t);
-     *
-     *     server.serve();
-     */
+    /// <summary>
+    /// <see cref="TMultiplexedProcessor"/> is a <see cref="TProcessor"/> allowing a single <see cref="Thrift.Server.TServer"/>
+    /// to provide multiple services.
+    /// <para/>
+    /// To do so, you instantiate the processor and then register additional processors with it,
+    /// as shown in the following example:
+    /// <para/>
+    /// <code>
+    ///     TMultiplexedProcessor processor = new TMultiplexedProcessor();
+    ///
+    ///     processor.registerProcessor(
+    ///         "Calculator",
+    ///         new Calculator.Processor(new CalculatorHandler()));
+    ///
+    ///     processor.registerProcessor(
+    ///         "WeatherReport",
+    ///         new WeatherReport.Processor(new WeatherReportHandler()));
+    ///
+    ///     TServerTransport t = new TServerSocket(9090);
+    ///     TSimpleServer server = new TSimpleServer(processor, t);
+    ///
+    ///     server.serve();
+    /// </code>
+    /// </summary>
     public class TMultiplexedProcessor : TProcessor
     {
-        private Dictionary<String,TProcessor> ServiceProcessorMap = new Dictionary<String,TProcessor>();
+        private Dictionary<string, TProcessor> ServiceProcessorMap = new Dictionary<string, TProcessor>();
 
-        /**
-         * 'Register' a service with this TMultiplexedProcessor. This allows us to broker
-         * requests to individual services by using the service name to select them at request time.
-         *
-         * Args:
-         * - serviceName    Name of a service, has to be identical to the name
-         *                  declared in the Thrift IDL, e.g. "WeatherReport".
-         * - processor      Implementation of a service, usually referred to as "handlers",
-         *                  e.g. WeatherReportHandler implementing WeatherReport.Iface.
-         */
-        public void RegisterProcessor(String serviceName, TProcessor processor)
+        /// <summary>
+        /// 'Register' a service with this TMultiplexedProcessor. This allows us to broker
+        /// requests to individual services by using the service name to select them at request time.
+        ///
+        /// Args:
+        /// - serviceName    Name of a service, has to be identical to the name
+        ///                  declared in the Thrift IDL, e.g. "WeatherReport".
+        /// - processor      Implementation of a service, usually referred to as "handlers",
+        ///                  e.g. WeatherReportHandler implementing WeatherReport.Iface.
+        /// </summary>
+        public void RegisterProcessor(string serviceName, TProcessor processor)
         {
             ServiceProcessorMap.Add(serviceName, processor);
         }
 
 
-        private void Fail( TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
+        private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
         {
-            TApplicationException appex = new TApplicationException( extype, etxt);
+            TApplicationException appex = new TApplicationException(extype, etxt);
 
             TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID);
 
             oprot.WriteMessageBegin(newMessage);
-            appex.Write( oprot);
+            appex.Write(oprot);
             oprot.WriteMessageEnd();
             oprot.Transport.Flush();
         }
 
 
-        /**
-         * This implementation of process performs the following steps:
-         *
-         * - Read the beginning of the message.
-         * - Extract the service name from the message.
-         * - Using the service name to locate the appropriate processor.
-         * - Dispatch to the processor, with a decorated instance of TProtocol
-         *    that allows readMessageBegin() to return the original TMessage.
-         *
-         * Throws an exception if
-         * - the message type is not CALL or ONEWAY,
-         * - the service name was not found in the message, or
-         * - the service name has not been RegisterProcessor()ed.
-         */
+        /// <summary>
+        /// This implementation of process performs the following steps:
+        ///
+        /// - Read the beginning of the message.
+        /// - Extract the service name from the message.
+        /// - Using the service name to locate the appropriate processor.
+        /// - Dispatch to the processor, with a decorated instance of TProtocol
+        ///    that allows readMessageBegin() to return the original TMessage.
+        /// <para/>
+        /// Throws an exception if
+        /// - the message type is not CALL or ONEWAY,
+        /// - the service name was not found in the message, or
+        /// - the service name has not been RegisterProcessor()ed.
+        /// </summary>
         public bool Process(TProtocol iprot, TProtocol oprot)
         {
             /*  Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
@@ -155,17 +158,17 @@
 
         }
 
-        /**
-         *  Our goal was to work with any protocol.  In order to do that, we needed
-         *  to allow them to call readMessageBegin() and get a TMessage in exactly
-         *  the standard format, without the service name prepended to TMessage.name.
-         */
+        /// <summary>
+        ///  Our goal was to work with any protocol.  In order to do that, we needed
+        ///  to allow them to call readMessageBegin() and get a TMessage in exactly
+        ///  the standard format, without the service name prepended to TMessage.name.
+        /// </summary>
         private class StoredMessageProtocol : TProtocolDecorator
         {
             TMessage MsgBegin;
 
             public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin)
-                :base(protocol)
+                : base(protocol)
             {
                 this.MsgBegin = messageBegin;
             }
diff --git a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
index 1e2af83..1bd420f 100644
--- a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
+++ b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
@@ -29,63 +29,62 @@
 namespace Thrift.Protocol
 {
 
-    /**
-     * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
-     * client to communicate with a multiplexing Thrift server, by prepending the service name
-     * to the function name during function calls.
-     *
-     * NOTE: THIS IS NOT TO BE USED BY SERVERS.
-     * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
-     *
-     * This example uses a single socket transport to invoke two services:
-     *
-     *     TSocket transport = new TSocket("localhost", 9090);
-     *     transport.open();
-     *
-     *     TBinaryProtocol protocol = new TBinaryProtocol(transport);
-     *
-     *     TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
-     *     Calculator.Client service = new Calculator.Client(mp);
-     *
-     *     TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
-     *     WeatherReport.Client service2 = new WeatherReport.Client(mp2);
-     *
-     *     System.out.println(service.add(2,2));
-     *     System.out.println(service2.getTemperature());
-     *
-     */
+    /// <summary>
+    /// TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
+    /// client to communicate with a multiplexing Thrift server, by prepending the service name
+    /// to the function name during function calls.
+    /// <para/>
+    /// NOTE: THIS IS NOT TO BE USED BY SERVERS.
+    /// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
+    /// <para/>
+    /// This example uses a single socket transport to invoke two services:
+    /// <code>
+    ///     TSocket transport = new TSocket("localhost", 9090);
+    ///     transport.open();
+    ///
+    ///     TBinaryProtocol protocol = new TBinaryProtocol(transport);
+    ///
+    ///     TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
+    ///     Calculator.Client service = new Calculator.Client(mp);
+    ///
+    ///     TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
+    ///     WeatherReport.Client service2 = new WeatherReport.Client(mp2);
+    ///
+    ///     System.out.println(service.add(2,2));
+    ///     System.out.println(service2.getTemperature());
+    /// </code>
+    /// </summary>
     public class TMultiplexedProtocol : TProtocolDecorator
     {
 
-        /** Used to delimit the service name from the function name */
-        public static String SEPARATOR = ":";
+        /// <summary>
+        /// Used to delimit the service name from the function name.
+        /// </summary>
+        public static string SEPARATOR = ":";
 
-        private String ServiceName;
+        private string ServiceName;
 
-        /**
-         * Wrap the specified protocol, allowing it to be used to communicate with a
-         * multiplexing server.  The <code>serviceName</code> is required as it is
-         * prepended to the message header so that the multiplexing server can broker
-         * the function call to the proper service.
-         *
-         * Args:
-         *  protocol        Your communication protocol of choice, e.g. TBinaryProtocol
-         *  serviceName     The service name of the service communicating via this protocol.
-         */
-        public TMultiplexedProtocol(TProtocol protocol, String serviceName)
+        /// <summary>
+        /// Wrap the specified protocol, allowing it to be used to communicate with a
+        /// multiplexing server.  The <paramref name="serviceName"/> is required as it is
+        /// prepended to the message header so that the multiplexing server can broker
+        /// the function call to the proper service.
+        /// </summary>
+        /// <param name="protocol">Your communication protocol of choice, e.g. <see cref="TBinaryProtocol"/>.</param>
+        /// <param name="serviceName">The service name of the service communicating via this protocol.</param>
+        public TMultiplexedProtocol(TProtocol protocol, string serviceName)
             : base(protocol)
         {
             ServiceName = serviceName;
         }
 
-        /**
-         * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
-         * Args:
-         *   tMessage     The original message.
-         */
+        /// <summary>
+        /// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
+        /// </summary>
+        /// <param name="tMessage">The original message.</param>
         public override void WriteMessageBegin(TMessage tMessage)
         {
-            switch(tMessage.Type)
+            switch (tMessage.Type)
             {
                 case TMessageType.Call:
                 case TMessageType.Oneway:
@@ -101,5 +100,4 @@
             }
         }
     }
-
 }
diff --git a/lib/csharp/src/Protocol/TProtocol.cs b/lib/csharp/src/Protocol/TProtocol.cs
index bf481ab..dd7a6e0 100644
--- a/lib/csharp/src/Protocol/TProtocol.cs
+++ b/lib/csharp/src/Protocol/TProtocol.cs
@@ -108,7 +108,8 @@
         public abstract void WriteI32(int i32);
         public abstract void WriteI64(long i64);
         public abstract void WriteDouble(double d);
-        public virtual void WriteString(string s) {
+        public virtual void WriteString(string s)
+        {
             WriteBinary(Encoding.UTF8.GetBytes(s));
         }
         public abstract void WriteBinary(byte[] b);
@@ -131,7 +132,8 @@
         public abstract int ReadI32();
         public abstract long ReadI64();
         public abstract double ReadDouble();
-        public virtual string ReadString() {
+        public virtual string ReadString()
+        {
             var buf = ReadBinary();
             return Encoding.UTF8.GetString(buf, 0, buf.Length);
         }
diff --git a/lib/csharp/src/Protocol/TProtocolDecorator.cs b/lib/csharp/src/Protocol/TProtocolDecorator.cs
index 7bc34ef..8600002 100644
--- a/lib/csharp/src/Protocol/TProtocolDecorator.cs
+++ b/lib/csharp/src/Protocol/TProtocolDecorator.cs
@@ -28,26 +28,25 @@
 
 namespace Thrift.Protocol
 {
-
-    /**
-     * TProtocolDecorator forwards all requests to an enclosed TProtocol instance,
-     * providing a way to author concise concrete decorator subclasses.  While it has
-     * no abstract methods, it is marked abstract as a reminder that by itself,
-     * it does not modify the behaviour of the enclosed TProtocol.
-     *
-     * See p.175 of Design Patterns (by Gamma et al.)
-     * See TMultiplexedProtocol
-     */
+    /// <summary>
+    /// <see cref="TProtocolDecorator"/> forwards all requests to an enclosed <see cref="TProtocol"/> instance,
+    /// providing a way to author concise concrete decorator subclasses. While it has
+    /// no abstract methods, it is marked abstract as a reminder that by itself,
+    /// it does not modify the behaviour of the enclosed <see cref="TProtocol"/>.
+    /// <para/>
+    /// See p.175 of Design Patterns (by Gamma et al.)
+    /// </summary>
+    /// <seealso cref="TMultiplexedProtocol"/>
     public abstract class TProtocolDecorator : TProtocol
     {
         private TProtocol WrappedProtocol;
 
-        /**
-         * Encloses the specified protocol.
-         * @param protocol All operations will be forward to this protocol.  Must be non-null.
-         */
+        /// <summary>
+        /// Encloses the specified protocol.
+        /// </summary>
+        /// <param name="protocol">All operations will be forward to this protocol.  Must be non-null.</param>
         public TProtocolDecorator(TProtocol protocol)
-            : base( protocol.Transport)
+            : base(protocol.Transport)
         {
 
             WrappedProtocol = protocol;
@@ -104,7 +103,7 @@
         }
 
         public override void WriteListEnd()
-{
+        {
             WrappedProtocol.WriteListEnd();
         }
 
@@ -148,7 +147,7 @@
             WrappedProtocol.WriteDouble(v);
         }
 
-        public override void WriteString(String s)
+        public override void WriteString(string s)
         {
             WrappedProtocol.WriteString(s);
         }
@@ -248,7 +247,7 @@
             return WrappedProtocol.ReadDouble();
         }
 
-        public override String ReadString()
+        public override string ReadString()
         {
             return WrappedProtocol.ReadString();
         }
diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs
index 76c749d..c0f007e 100644
--- a/lib/csharp/src/Protocol/TProtocolException.cs
+++ b/lib/csharp/src/Protocol/TProtocolException.cs
@@ -48,14 +48,14 @@
             type_ = type;
         }
 
-        public TProtocolException(int type, String message)
-            : base(message)
+        public TProtocolException(int type, string message, Exception inner = null)
+            : base(message, inner)
         {
             type_ = type;
         }
 
-        public TProtocolException(String message)
-            : base(message)
+        public TProtocolException(string message, Exception inner = null)
+            : base(message, inner)
         {
         }
 
diff --git a/lib/csharp/src/Protocol/TProtocolUtil.cs b/lib/csharp/src/Protocol/TProtocolUtil.cs
index 0606c71..d995c6c 100644
--- a/lib/csharp/src/Protocol/TProtocolUtil.cs
+++ b/lib/csharp/src/Protocol/TProtocolUtil.cs
@@ -98,7 +98,6 @@
                     default:
                         throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
                 }
-
             }
             finally
             {
diff --git a/lib/csharp/src/Server/TServer.cs b/lib/csharp/src/Server/TServer.cs
index 34f06a9..2bc04f3 100644
--- a/lib/csharp/src/Server/TServer.cs
+++ b/lib/csharp/src/Server/TServer.cs
@@ -28,128 +28,128 @@
 
 namespace Thrift.Server
 {
-  public abstract class TServer
-  {
-    //Attributes
-    protected TProcessorFactory processorFactory;
-    protected TServerTransport serverTransport;
-    protected TTransportFactory inputTransportFactory;
-    protected TTransportFactory outputTransportFactory;
-    protected TProtocolFactory inputProtocolFactory;
-    protected TProtocolFactory outputProtocolFactory;
-    protected TServerEventHandler serverEventHandler = null;
+    public abstract class TServer
+    {
+        //Attributes
+        protected TProcessorFactory processorFactory;
+        protected TServerTransport serverTransport;
+        protected TTransportFactory inputTransportFactory;
+        protected TTransportFactory outputTransportFactory;
+        protected TProtocolFactory inputProtocolFactory;
+        protected TProtocolFactory outputProtocolFactory;
+        protected TServerEventHandler serverEventHandler = null;
 
-    //Methods
-    public void setEventHandler(TServerEventHandler seh)
-    {
-      serverEventHandler = seh;
-    }
-    public TServerEventHandler getEventHandler()
-    {
-      return serverEventHandler;
-    }
+        //Methods
+        public void setEventHandler(TServerEventHandler seh)
+        {
+            serverEventHandler = seh;
+        }
+        public TServerEventHandler getEventHandler()
+        {
+            return serverEventHandler;
+        }
 
-    //Log delegation
-    public delegate void LogDelegate(string str);
-    private LogDelegate _logDelegate;
-    protected LogDelegate logDelegate
-    {
-      get { return _logDelegate; }
-      set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
-    }
-    protected static void DefaultLogDelegate(string s)
-    {
-      Console.Error.WriteLine(s);
-    }
+        //Log delegation
+        public delegate void LogDelegate(string str);
+        private LogDelegate _logDelegate;
+        protected LogDelegate logDelegate
+        {
+            get { return _logDelegate; }
+            set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
+        }
+        protected static void DefaultLogDelegate(string s)
+        {
+            Console.Error.WriteLine(s);
+        }
 
-    //Construction
-    public TServer(TProcessor processor,
-              TServerTransport serverTransport)
-      : this(processor, serverTransport,
-         new TTransportFactory(),
-         new TTransportFactory(),
-         new TBinaryProtocol.Factory(),
-         new TBinaryProtocol.Factory(),
-         DefaultLogDelegate)
-    {
-    }
+        //Construction
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport)
+          : this(processor, serverTransport,
+             new TTransportFactory(),
+             new TTransportFactory(),
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             DefaultLogDelegate)
+        {
+        }
 
-    public TServer(TProcessor processor,
+        public TServer(TProcessor processor,
+                TServerTransport serverTransport,
+                LogDelegate logDelegate)
+          : this(processor,
+             serverTransport,
+             new TTransportFactory(),
+             new TTransportFactory(),
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             logDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory)
+          : this(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             DefaultLogDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory,
+                  TProtocolFactory protocolFactory)
+          : this(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             protocolFactory,
+             protocolFactory,
+               DefaultLogDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
             TServerTransport serverTransport,
+            TTransportFactory inputTransportFactory,
+            TTransportFactory outputTransportFactory,
+            TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory,
             LogDelegate logDelegate)
-      : this(processor,
-         serverTransport,
-         new TTransportFactory(),
-         new TTransportFactory(),
-         new TBinaryProtocol.Factory(),
-         new TBinaryProtocol.Factory(),
-         logDelegate)
-    {
-    }
+        {
+            this.processorFactory = new TSingletonProcessorFactory(processor);
+            this.serverTransport = serverTransport;
+            this.inputTransportFactory = inputTransportFactory;
+            this.outputTransportFactory = outputTransportFactory;
+            this.inputProtocolFactory = inputProtocolFactory;
+            this.outputProtocolFactory = outputProtocolFactory;
+            this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
+        }
 
-    public TServer(TProcessor processor,
-              TServerTransport serverTransport,
-              TTransportFactory transportFactory)
-      : this(processor,
-         serverTransport,
-         transportFactory,
-         transportFactory,
-         new TBinaryProtocol.Factory(),
-         new TBinaryProtocol.Factory(),
-         DefaultLogDelegate)
-    {
-    }
+        public TServer(TProcessorFactory processorFactory,
+                  TServerTransport serverTransport,
+                  TTransportFactory inputTransportFactory,
+                  TTransportFactory outputTransportFactory,
+                  TProtocolFactory inputProtocolFactory,
+                  TProtocolFactory outputProtocolFactory,
+                  LogDelegate logDelegate)
+        {
+            this.processorFactory = processorFactory;
+            this.serverTransport = serverTransport;
+            this.inputTransportFactory = inputTransportFactory;
+            this.outputTransportFactory = outputTransportFactory;
+            this.inputProtocolFactory = inputProtocolFactory;
+            this.outputProtocolFactory = outputProtocolFactory;
+            this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
+        }
 
-    public TServer(TProcessor processor,
-              TServerTransport serverTransport,
-              TTransportFactory transportFactory,
-              TProtocolFactory protocolFactory)
-      : this(processor,
-         serverTransport,
-         transportFactory,
-         transportFactory,
-         protocolFactory,
-         protocolFactory,
-           DefaultLogDelegate)
-    {
+        //Abstract Interface
+        public abstract void Serve();
+        public abstract void Stop();
     }
-
-    public TServer(TProcessor processor,
-        TServerTransport serverTransport,
-        TTransportFactory inputTransportFactory,
-        TTransportFactory outputTransportFactory,
-        TProtocolFactory inputProtocolFactory,
-        TProtocolFactory outputProtocolFactory,
-        LogDelegate logDelegate)
-    {
-        this.processorFactory = new TSingletonProcessorFactory(processor);
-        this.serverTransport = serverTransport;
-        this.inputTransportFactory = inputTransportFactory;
-        this.outputTransportFactory = outputTransportFactory;
-        this.inputProtocolFactory = inputProtocolFactory;
-        this.outputProtocolFactory = outputProtocolFactory;
-        this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
-    }
-
-    public TServer(TProcessorFactory processorFactory,
-              TServerTransport serverTransport,
-              TTransportFactory inputTransportFactory,
-              TTransportFactory outputTransportFactory,
-              TProtocolFactory inputProtocolFactory,
-              TProtocolFactory outputProtocolFactory,
-              LogDelegate logDelegate)
-    {
-        this.processorFactory = processorFactory;
-        this.serverTransport = serverTransport;
-        this.inputTransportFactory = inputTransportFactory;
-        this.outputTransportFactory = outputTransportFactory;
-        this.inputProtocolFactory = inputProtocolFactory;
-        this.outputProtocolFactory = outputProtocolFactory;
-        this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
-    }
-
-    //Abstract Interface
-    public abstract void Serve();
-    public abstract void Stop();
-  }
 }
diff --git a/lib/csharp/src/Server/TServerEventHandler.cs b/lib/csharp/src/Server/TServerEventHandler.cs
index 843b166..e81efc6 100644
--- a/lib/csharp/src/Server/TServerEventHandler.cs
+++ b/lib/csharp/src/Server/TServerEventHandler.cs
@@ -25,26 +25,29 @@
 
 namespace Thrift.Server
 {
-  /// <summary>
-  /// Interface implemented by server users to handle events from the server
-  /// </summary>
-  public interface TServerEventHandler
-  {
     /// <summary>
-    /// Called before the server begins */
+    /// Interface implemented by server users to handle events from the server.
     /// </summary>
-    void preServe();
-    /// <summary>
-    /// Called when a new client has connected and is about to being processing */
-    /// </summary>
-    Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
-    /// <summary>
-    /// Called when a client has finished request-handling to delete server context */
-    /// </summary>
-    void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
-    /// <summary>
-    /// Called when a client is about to call the processor */
-    /// </summary>
-    void processContext(Object serverContext, Thrift.Transport.TTransport transport);
-  };
+    public interface TServerEventHandler
+    {
+        /// <summary>
+        /// Called before the server begins.
+        /// </summary>
+        void preServe();
+
+        /// <summary>
+        /// Called when a new client has connected and is about to being processing.
+        /// </summary>
+        object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
+
+        /// <summary>
+        /// Called when a client has finished request-handling to delete server context.
+        /// </summary>
+        void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
+
+        /// <summary>
+        /// Called when a client is about to call the processor.
+        /// </summary>
+        void processContext(object serverContext, Thrift.Transport.TTransport transport);
+    };
 }
diff --git a/lib/csharp/src/Server/TSimpleServer.cs b/lib/csharp/src/Server/TSimpleServer.cs
index c73fecf..4e7ea96 100644
--- a/lib/csharp/src/Server/TSimpleServer.cs
+++ b/lib/csharp/src/Server/TSimpleServer.cs
@@ -27,154 +27,154 @@
 
 namespace Thrift.Server
 {
-  /// <summary>
-  /// Simple single-threaded server for testing
-  /// </summary>
-  public class TSimpleServer : TServer
-  {
-    private bool stop = false;
-
-    public TSimpleServer(TProcessor processor,
-              TServerTransport serverTransport)
-      : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
+    /// <summary>
+    /// Simple single-threaded server for testing.
+    /// </summary>
+    public class TSimpleServer : TServer
     {
-    }
+        private bool stop = false;
 
-    public TSimpleServer(TProcessor processor,
-              TServerTransport serverTransport,
-              LogDelegate logDel)
-      : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
-    {
-    }
-
-    public TSimpleServer(TProcessor processor,
-              TServerTransport serverTransport,
-              TTransportFactory transportFactory)
-      : base(processor,
-         serverTransport,
-         transportFactory,
-         transportFactory,
-         new TBinaryProtocol.Factory(),
-         new TBinaryProtocol.Factory(),
-           DefaultLogDelegate)
-    {
-    }
-
-    public TSimpleServer(TProcessor processor,
-        TServerTransport serverTransport,
-        TTransportFactory transportFactory,
-        TProtocolFactory protocolFactory)
-        : base(processor,
-           serverTransport,
-           transportFactory,
-           transportFactory,
-           protocolFactory,
-           protocolFactory,
-           DefaultLogDelegate)
-    {
-    }
-
-    public TSimpleServer(TProcessorFactory processorFactory,
-              TServerTransport serverTransport,
-              TTransportFactory transportFactory,
-              TProtocolFactory protocolFactory)
-      : base(processorFactory,
-         serverTransport,
-         transportFactory,
-         transportFactory,
-         protocolFactory,
-         protocolFactory,
-         DefaultLogDelegate)
-    {
-    }
-
-    public override void Serve()
-    {
-      try
-      {
-        serverTransport.Listen();
-      }
-      catch (TTransportException ttx)
-      {
-        logDelegate(ttx.ToString());
-        return;
-      }
-
-      //Fire the preServe server event when server is up but before any client connections
-      if (serverEventHandler != null)
-        serverEventHandler.preServe();
-
-      while (!stop)
-      {
-        TProcessor processor = null;
-        TTransport client = null;
-        TTransport inputTransport = null;
-        TTransport outputTransport = null;
-        TProtocol inputProtocol = null;
-        TProtocol outputProtocol = null;
-        Object connectionContext = null;
-        try
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport)
+          : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
         {
-          using (client = serverTransport.Accept())
-          {
-            processor = processorFactory.GetProcessor(client);
-            if (client != null)
+        }
+
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  LogDelegate logDel)
+          : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
+        {
+        }
+
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory)
+          : base(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+               DefaultLogDelegate)
+        {
+        }
+
+        public TSimpleServer(TProcessor processor,
+            TServerTransport serverTransport,
+            TTransportFactory transportFactory,
+            TProtocolFactory protocolFactory)
+            : base(processor,
+               serverTransport,
+               transportFactory,
+               transportFactory,
+               protocolFactory,
+               protocolFactory,
+               DefaultLogDelegate)
+        {
+        }
+
+        public TSimpleServer(TProcessorFactory processorFactory,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory,
+                  TProtocolFactory protocolFactory)
+          : base(processorFactory,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             protocolFactory,
+             protocolFactory,
+             DefaultLogDelegate)
+        {
+        }
+
+        public override void Serve()
+        {
+            try
             {
-              using (inputTransport = inputTransportFactory.GetTransport(client))
-              {
-                using (outputTransport = outputTransportFactory.GetTransport(client))
-                {
-                  inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
-                  outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
-
-                  //Recover event handler (if any) and fire createContext server event when a client connects
-                  if (serverEventHandler != null)
-                    connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
-
-                  //Process client requests until client disconnects
-                  while (!stop)
-                  {
-                    if (!inputTransport.Peek())
-                      break;
-
-                    //Fire processContext server event
-                    //N.B. This is the pattern implemented in C++ and the event fires provisionally.
-                    //That is to say it may be many minutes between the event firing and the client request
-                    //actually arriving or the client may hang up without ever makeing a request.
-                    if (serverEventHandler != null)
-                      serverEventHandler.processContext(connectionContext, inputTransport);
-                    //Process client request (blocks until transport is readable)
-                    if (!processor.Process(inputProtocol, outputProtocol))
-                      break;
-                  }
-                }
-              }
+                serverTransport.Listen();
             }
-          }
-        }
-        catch (TTransportException ttx)
-        {
-          if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
-          {
-            logDelegate(ttx.ToString());
-          }
-        }
-        catch (Exception x)
-        {
-          //Unexpected
-          logDelegate(x.ToString());
+            catch (TTransportException ttx)
+            {
+                logDelegate(ttx.ToString());
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
+            if (serverEventHandler != null)
+                serverEventHandler.preServe();
+
+            while (!stop)
+            {
+                TProcessor processor = null;
+                TTransport client = null;
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    using (client = serverTransport.Accept())
+                    {
+                        processor = processorFactory.GetProcessor(client);
+                        if (client != null)
+                        {
+                            using (inputTransport = inputTransportFactory.GetTransport(client))
+                            {
+                                using (outputTransport = outputTransportFactory.GetTransport(client))
+                                {
+                                    inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                                    outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                                    //Recover event handler (if any) and fire createContext server event when a client connects
+                                    if (serverEventHandler != null)
+                                        connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                                    //Process client requests until client disconnects
+                                    while (!stop)
+                                    {
+                                        if (!inputTransport.Peek())
+                                            break;
+
+                                        //Fire processContext server event
+                                        //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                                        //That is to say it may be many minutes between the event firing and the client request
+                                        //actually arriving or the client may hang up without ever makeing a request.
+                                        if (serverEventHandler != null)
+                                            serverEventHandler.processContext(connectionContext, inputTransport);
+                                        //Process client request (blocks until transport is readable)
+                                        if (!processor.Process(inputProtocol, outputProtocol))
+                                            break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        logDelegate(ttx.ToString());
+                    }
+                }
+                catch (Exception x)
+                {
+                    //Unexpected
+                    logDelegate(x.ToString());
+                }
+
+                //Fire deleteContext server event after client disconnects
+                if (serverEventHandler != null)
+                    serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+            }
         }
 
-        //Fire deleteContext server event after client disconnects
-        if (serverEventHandler != null)
-          serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
-      }
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+        }
     }
-
-    public override void Stop()
-    {
-      stop = true;
-      serverTransport.Close();
-    }
-  }
 }
diff --git a/lib/csharp/src/Server/TThreadPoolServer.cs b/lib/csharp/src/Server/TThreadPoolServer.cs
index b7346b8..a494ce7 100644
--- a/lib/csharp/src/Server/TThreadPoolServer.cs
+++ b/lib/csharp/src/Server/TThreadPoolServer.cs
@@ -28,250 +28,268 @@
 
 namespace Thrift.Server
 {
-  /// <summary>
-  /// Server that uses C# built-in ThreadPool to spawn threads when handling requests
-  /// </summary>
-  public class TThreadPoolServer : TServer
-  {
-    private const int DEFAULT_MIN_THREADS = -1;  // use .NET ThreadPool defaults
-    private const int DEFAULT_MAX_THREADS = -1;  // use .NET ThreadPool defaults
-    private volatile bool stop = false;
-
-    public struct Configuration
-    {
-      public int MinWorkerThreads;
-      public int MaxWorkerThreads;
-      public int MinIOThreads;
-      public int MaxIOThreads;
-
-      public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
-      {
-        MinWorkerThreads = min;
-        MaxWorkerThreads = max;
-        MinIOThreads = min;
-        MaxIOThreads = max;
-      }
-
-      public Configuration(int minWork, int maxWork, int minIO, int maxIO)
-      {
-        MinWorkerThreads = minWork;
-        MaxWorkerThreads = maxWork;
-        MinIOThreads = minIO;
-        MaxIOThreads = maxIO;
-      }
-    }
-
-    public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-         new TTransportFactory(), new TTransportFactory(),
-         new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
-         new Configuration(), DefaultLogDelegate)
-    {
-    }
-
-    public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-         new TTransportFactory(), new TTransportFactory(),
-         new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
-         new Configuration(), logDelegate)
-    {
-    }
-
-    public TThreadPoolServer(TProcessor processor,
-     TServerTransport serverTransport,
-     TTransportFactory transportFactory,
-     TProtocolFactory protocolFactory)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-           transportFactory, transportFactory,
-           protocolFactory, protocolFactory,
-           new Configuration(), DefaultLogDelegate)
-    {
-    }
-
-    public TThreadPoolServer(TProcessorFactory processorFactory,
-                 TServerTransport serverTransport,
-                 TTransportFactory transportFactory,
-                 TProtocolFactory protocolFactory)
-        : this(processorFactory, serverTransport,
-         transportFactory, transportFactory,
-         protocolFactory, protocolFactory,
-         new Configuration(), DefaultLogDelegate)
-    {
-    }
-
-    public TThreadPoolServer(TProcessorFactory processorFactory,
-                 TServerTransport serverTransport,
-                 TTransportFactory inputTransportFactory,
-                 TTransportFactory outputTransportFactory,
-                 TProtocolFactory inputProtocolFactory,
-                 TProtocolFactory outputProtocolFactory,
-                 int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
-        : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
-         inputProtocolFactory, outputProtocolFactory,
-         new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
-         logDel)
-    {
-    }
-
-    public TThreadPoolServer(TProcessorFactory processorFactory,
-                 TServerTransport serverTransport,
-                 TTransportFactory inputTransportFactory,
-                 TTransportFactory outputTransportFactory,
-                 TProtocolFactory inputProtocolFactory,
-                 TProtocolFactory outputProtocolFactory,
-                 Configuration threadConfig,
-                 LogDelegate logDel)
-        : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
-        inputProtocolFactory, outputProtocolFactory, logDel)
-    {
-      lock (typeof(TThreadPoolServer))
-      {
-        if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
-        {
-          int work, comm;
-          ThreadPool.GetMaxThreads(out work, out comm);
-          if (threadConfig.MaxWorkerThreads > 0)
-            work = threadConfig.MaxWorkerThreads;
-          if (threadConfig.MaxIOThreads > 0)
-            comm = threadConfig.MaxIOThreads;
-          if (!ThreadPool.SetMaxThreads(work, comm))
-            throw new Exception("Error: could not SetMaxThreads in ThreadPool");
-        }
-
-        if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
-        {
-          int work, comm;
-          ThreadPool.GetMinThreads(out work, out comm);
-          if (threadConfig.MinWorkerThreads > 0)
-            work = threadConfig.MinWorkerThreads;
-          if (threadConfig.MinIOThreads > 0)
-            comm = threadConfig.MinIOThreads;
-          if (!ThreadPool.SetMinThreads(work, comm))
-            throw new Exception("Error: could not SetMinThreads in ThreadPool");
-        }
-      }
-    }
-
-
     /// <summary>
-    /// Use new ThreadPool thread for each new client connection
+    /// Server that uses C# built-in ThreadPool to spawn threads when handling requests.
     /// </summary>
-    public override void Serve()
+    public class TThreadPoolServer : TServer
     {
-      try
-      {
-        serverTransport.Listen();
-      }
-      catch (TTransportException ttx)
-      {
-        logDelegate("Error, could not listen on ServerTransport: " + ttx);
-        return;
-      }
+        private const int DEFAULT_MIN_THREADS = -1;  // use .NET ThreadPool defaults
+        private const int DEFAULT_MAX_THREADS = -1;  // use .NET ThreadPool defaults
+        private volatile bool stop = false;
 
-      //Fire the preServe server event when server is up but before any client connections
-      if (serverEventHandler != null)
-        serverEventHandler.preServe();
+        public struct Configuration
+        {
+            public int MinWorkerThreads;
+            public int MaxWorkerThreads;
+            public int MinIOThreads;
+            public int MaxIOThreads;
 
-      while (!stop)
-      {
-        int failureCount = 0;
-        try
-        {
-          TTransport client = serverTransport.Accept();
-          ThreadPool.QueueUserWorkItem(this.Execute, client);
-        }
-        catch (TTransportException ttx)
-        {
-          if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
-          {
-            ++failureCount;
-            logDelegate(ttx.ToString());
-          }
+            public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
+            {
+                MinWorkerThreads = min;
+                MaxWorkerThreads = max;
+                MinIOThreads = min;
+                MaxIOThreads = max;
+            }
 
+            public Configuration(int minWork, int maxWork, int minIO, int maxIO)
+            {
+                MinWorkerThreads = minWork;
+                MaxWorkerThreads = maxWork;
+                MinIOThreads = minIO;
+                MaxIOThreads = maxIO;
+            }
         }
-      }
 
-      if (stop)
-      {
-        try
+        public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             new Configuration(), DefaultLogDelegate)
         {
-          serverTransport.Close();
         }
-        catch (TTransportException ttx)
+
+        public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             new Configuration(), logDelegate)
         {
-          logDelegate("TServerTransport failed on close: " + ttx.Message);
         }
-        stop = false;
-      }
+
+        public TThreadPoolServer(TProcessor processor,
+         TServerTransport serverTransport,
+         TTransportFactory transportFactory,
+         TProtocolFactory protocolFactory)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+               transportFactory, transportFactory,
+               protocolFactory, protocolFactory,
+               new Configuration(), DefaultLogDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory transportFactory,
+                     TProtocolFactory protocolFactory)
+            : this(processorFactory, serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             new Configuration(), DefaultLogDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
+            : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+             inputProtocolFactory, outputProtocolFactory,
+             new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
+             logDel)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     Configuration threadConfig,
+                     LogDelegate logDel)
+            : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+            inputProtocolFactory, outputProtocolFactory, logDel)
+        {
+            lock (typeof(TThreadPoolServer))
+            {
+                if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
+                {
+                    int work, comm;
+                    ThreadPool.GetMaxThreads(out work, out comm);
+                    if (threadConfig.MaxWorkerThreads > 0)
+                        work = threadConfig.MaxWorkerThreads;
+                    if (threadConfig.MaxIOThreads > 0)
+                        comm = threadConfig.MaxIOThreads;
+                    if (!ThreadPool.SetMaxThreads(work, comm))
+                        throw new Exception("Error: could not SetMaxThreads in ThreadPool");
+                }
+
+                if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
+                {
+                    int work, comm;
+                    ThreadPool.GetMinThreads(out work, out comm);
+                    if (threadConfig.MinWorkerThreads > 0)
+                        work = threadConfig.MinWorkerThreads;
+                    if (threadConfig.MinIOThreads > 0)
+                        comm = threadConfig.MinIOThreads;
+                    if (!ThreadPool.SetMinThreads(work, comm))
+                        throw new Exception("Error: could not SetMinThreads in ThreadPool");
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Use new ThreadPool thread for each new client connection.
+        /// </summary>
+        public override void Serve()
+        {
+            try
+            {
+                serverTransport.Listen();
+            }
+            catch (TTransportException ttx)
+            {
+                logDelegate("Error, could not listen on ServerTransport: " + ttx);
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
+            if (serverEventHandler != null)
+                serverEventHandler.preServe();
+
+            while (!stop)
+            {
+                int failureCount = 0;
+                try
+                {
+                    TTransport client = serverTransport.Accept();
+                    ThreadPool.QueueUserWorkItem(this.Execute, client);
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        ++failureCount;
+                        logDelegate(ttx.ToString());
+                    }
+
+                }
+            }
+
+            if (stop)
+            {
+                try
+                {
+                    serverTransport.Close();
+                }
+                catch (TTransportException ttx)
+                {
+                    logDelegate("TServerTransport failed on close: " + ttx.Message);
+                }
+                stop = false;
+            }
+        }
+
+        /// <summary>
+        /// Loops on processing a client forever
+        /// threadContext will be a TTransport instance
+        /// </summary>
+        /// <param name="threadContext"></param>
+        private void Execute(object threadContext)
+        {
+            using (TTransport client = (TTransport)threadContext)
+            {
+                TProcessor processor = processorFactory.GetProcessor(client, this);
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    try
+                    {
+                        inputTransport = inputTransportFactory.GetTransport(client);
+                        outputTransport = outputTransportFactory.GetTransport(client);
+                        inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                        outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                        //Recover event handler (if any) and fire createContext server event when a client connects
+                        if (serverEventHandler != null)
+                            connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                        //Process client requests until client disconnects
+                        while (!stop)
+                        {
+                            if (!inputTransport.Peek())
+                                break;
+
+                            //Fire processContext server event
+                            //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                            //That is to say it may be many minutes between the event firing and the client request
+                            //actually arriving or the client may hang up without ever makeing a request.
+                            if (serverEventHandler != null)
+                                serverEventHandler.processContext(connectionContext, inputTransport);
+                            //Process client request (blocks until transport is readable)
+                            if (!processor.Process(inputProtocol, outputProtocol))
+                                break;
+                        }
+                    }
+                    catch (TTransportException)
+                    {
+                        //Usually a client disconnect, expected
+                    }
+                    catch (Exception x)
+                    {
+                        //Unexpected
+                        logDelegate("Error: " + x);
+                    }
+
+                    //Fire deleteContext server event after client disconnects
+                    if (serverEventHandler != null)
+                        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+
+                }
+                finally
+                {
+                    //Close transports
+                    if (inputTransport != null)
+                        inputTransport.Close();
+                    if (outputTransport != null)
+                        outputTransport.Close();
+
+                    // disposable stuff should be disposed
+                    if (inputProtocol != null)
+                        inputProtocol.Dispose();
+                    if (outputProtocol != null)
+                        outputProtocol.Dispose();
+                    if (inputTransport != null)
+                        inputTransport.Dispose();
+                    if (outputTransport != null)
+                        outputTransport.Dispose();
+                }
+            }
+        }
+
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+        }
     }
-
-    /// <summary>
-    /// Loops on processing a client forever
-    /// threadContext will be a TTransport instance
-    /// </summary>
-    /// <param name="threadContext"></param>
-    private void Execute(Object threadContext)
-    {
-      TTransport client = (TTransport)threadContext;
-      TProcessor processor = processorFactory.GetProcessor(client, this);
-      TTransport inputTransport = null;
-      TTransport outputTransport = null;
-      TProtocol inputProtocol = null;
-      TProtocol outputProtocol = null;
-      Object connectionContext = null;
-      try
-      {
-        inputTransport = inputTransportFactory.GetTransport(client);
-        outputTransport = outputTransportFactory.GetTransport(client);
-        inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
-        outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
-
-        //Recover event handler (if any) and fire createContext server event when a client connects
-        if (serverEventHandler != null)
-          connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
-
-        //Process client requests until client disconnects
-        while (!stop)
-        {
-          if (!inputTransport.Peek())
-            break;
-
-          //Fire processContext server event
-          //N.B. This is the pattern implemented in C++ and the event fires provisionally.
-          //That is to say it may be many minutes between the event firing and the client request
-          //actually arriving or the client may hang up without ever makeing a request.
-          if (serverEventHandler != null)
-            serverEventHandler.processContext(connectionContext, inputTransport);
-          //Process client request (blocks until transport is readable)
-          if (!processor.Process(inputProtocol, outputProtocol))
-            break;
-        }
-      }
-      catch (TTransportException)
-      {
-        //Usually a client disconnect, expected
-      }
-      catch (Exception x)
-      {
-        //Unexpected
-        logDelegate("Error: " + x);
-      }
-
-      //Fire deleteContext server event after client disconnects
-      if (serverEventHandler != null)
-        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
-
-      //Close transports
-      if (inputTransport != null)
-        inputTransport.Close();
-      if (outputTransport != null)
-        outputTransport.Close();
-    }
-
-    public override void Stop()
-    {
-      stop = true;
-      serverTransport.Close();
-    }
-  }
 }
diff --git a/lib/csharp/src/Server/TThreadedServer.cs b/lib/csharp/src/Server/TThreadedServer.cs
index fe13dfd..cc051a3 100644
--- a/lib/csharp/src/Server/TThreadedServer.cs
+++ b/lib/csharp/src/Server/TThreadedServer.cs
@@ -26,243 +26,257 @@
 
 namespace Thrift.Server
 {
-  /// <summary>
-  /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests
-  /// </summary>
-  public class TThreadedServer : TServer
-  {
-    private const int DEFAULT_MAX_THREADS = 100;
-    private volatile bool stop = false;
-    private readonly int maxThreads;
-
-    private Queue<TTransport> clientQueue;
-    private THashSet<Thread> clientThreads;
-    private object clientLock;
-    private Thread workerThread;
-
-    public int ClientThreadsCount  {
-        get { return clientThreads.Count; }
-    }
-
-    public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-         new TTransportFactory(), new TTransportFactory(),
-         new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
-         DEFAULT_MAX_THREADS, DefaultLogDelegate)
-    {
-    }
-
-    public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-         new TTransportFactory(), new TTransportFactory(),
-         new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
-         DEFAULT_MAX_THREADS, logDelegate)
-    {
-    }
-
-
-    public TThreadedServer(TProcessor processor,
-                 TServerTransport serverTransport,
-                 TTransportFactory transportFactory,
-                 TProtocolFactory protocolFactory)
-        : this(new TSingletonProcessorFactory(processor), serverTransport,
-         transportFactory, transportFactory,
-         protocolFactory, protocolFactory,
-         DEFAULT_MAX_THREADS, DefaultLogDelegate)
-    {
-    }
-
-    public TThreadedServer(TProcessorFactory processorFactory,
-           TServerTransport serverTransport,
-           TTransportFactory transportFactory,
-           TProtocolFactory protocolFactory)
-        : this(processorFactory, serverTransport,
-         transportFactory, transportFactory,
-         protocolFactory, protocolFactory,
-         DEFAULT_MAX_THREADS, DefaultLogDelegate)
-    {
-    }
-    public TThreadedServer(TProcessorFactory processorFactory,
-                 TServerTransport serverTransport,
-                 TTransportFactory inputTransportFactory,
-                 TTransportFactory outputTransportFactory,
-                 TProtocolFactory inputProtocolFactory,
-                 TProtocolFactory outputProtocolFactory,
-                 int maxThreads, LogDelegate logDel)
-      : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
-          inputProtocolFactory, outputProtocolFactory, logDel)
-    {
-      this.maxThreads = maxThreads;
-      clientQueue = new Queue<TTransport>();
-      clientLock = new object();
-      clientThreads = new THashSet<Thread>();
-    }
-
     /// <summary>
-    /// Use new Thread for each new client connection. block until numConnections < maxThreads
+    /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests.
     /// </summary>
-    public override void Serve()
+    public class TThreadedServer : TServer
     {
-      try
-      {
-        //start worker thread
-        workerThread = new Thread(new ThreadStart(Execute));
-        workerThread.Start();
-        serverTransport.Listen();
-      }
-      catch (TTransportException ttx)
-      {
-        logDelegate("Error, could not listen on ServerTransport: " + ttx);
-        return;
-      }
+        private const int DEFAULT_MAX_THREADS = 100;
+        private volatile bool stop = false;
+        private readonly int maxThreads;
 
-      //Fire the preServe server event when server is up but before any client connections
-      if (serverEventHandler != null)
-        serverEventHandler.preServe();
+        private Queue<TTransport> clientQueue;
+        private THashSet<Thread> clientThreads;
+        private object clientLock;
+        private Thread workerThread;
 
-      while (!stop)
-      {
-        int failureCount = 0;
-        try
+        public int ClientThreadsCount
         {
-          TTransport client = serverTransport.Accept();
-          lock (clientLock)
-          {
-            clientQueue.Enqueue(client);
-            Monitor.Pulse(clientLock);
-          }
+            get { return clientThreads.Count; }
         }
-        catch (TTransportException ttx)
-        {
-          if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
-          {
-            ++failureCount;
-            logDelegate(ttx.ToString());
-          }
 
+        public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
+        {
         }
-      }
 
-      if (stop)
-      {
-        try
+        public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             DEFAULT_MAX_THREADS, logDelegate)
         {
-          serverTransport.Close();
         }
-        catch (TTransportException ttx)
+
+
+        public TThreadedServer(TProcessor processor,
+                     TServerTransport serverTransport,
+                     TTransportFactory transportFactory,
+                     TProtocolFactory protocolFactory)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
         {
-          logDelegate("TServeTransport failed on close: " + ttx.Message);
         }
-        stop = false;
-      }
-    }
 
-    /// <summary>
-    /// Loops on processing a client forever
-    /// threadContext will be a TTransport instance
-    /// </summary>
-    /// <param name="threadContext"></param>
-    private void Execute()
-    {
-      while (!stop)
-      {
-        TTransport client;
-        Thread t;
-        lock (clientLock)
+        public TThreadedServer(TProcessorFactory processorFactory,
+               TServerTransport serverTransport,
+               TTransportFactory transportFactory,
+               TProtocolFactory protocolFactory)
+            : this(processorFactory, serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
         {
-          //don't dequeue if too many connections
-          while (clientThreads.Count >= maxThreads)
-          {
-            Monitor.Wait(clientLock);
-          }
-
-          while (clientQueue.Count == 0)
-          {
-            Monitor.Wait(clientLock);
-          }
-
-          client = clientQueue.Dequeue();
-          t = new Thread(new ParameterizedThreadStart(ClientWorker));
-          clientThreads.Add(t);
         }
-        //start processing requests from client on new thread
-        t.Start(client);
-      }
-    }
-
-    private void ClientWorker(Object context)
-    {
-      TTransport client = (TTransport)context;
-      TProcessor processor = processorFactory.GetProcessor(client);
-      TTransport inputTransport = null;
-      TTransport outputTransport = null;
-      TProtocol inputProtocol = null;
-      TProtocol outputProtocol = null;
-      Object connectionContext = null;
-      try
-      {
-        using (inputTransport = inputTransportFactory.GetTransport(client))
+        public TThreadedServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     int maxThreads, LogDelegate logDel)
+          : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+              inputProtocolFactory, outputProtocolFactory, logDel)
         {
-          using (outputTransport = outputTransportFactory.GetTransport(client))
-          {
-            inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
-            outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+            this.maxThreads = maxThreads;
+            clientQueue = new Queue<TTransport>();
+            clientLock = new object();
+            clientThreads = new THashSet<Thread>();
+        }
 
-            //Recover event handler (if any) and fire createContext server event when a client connects
+        /// <summary>
+        /// Use new Thread for each new client connection. block until numConnections &lt; maxThreads.
+        /// </summary>
+        public override void Serve()
+        {
+            try
+            {
+                //start worker thread
+                workerThread = new Thread(new ThreadStart(Execute));
+                workerThread.Start();
+                serverTransport.Listen();
+            }
+            catch (TTransportException ttx)
+            {
+                logDelegate("Error, could not listen on ServerTransport: " + ttx);
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
             if (serverEventHandler != null)
-              connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+                serverEventHandler.preServe();
 
-            //Process client requests until client disconnects
             while (!stop)
             {
-              if (!inputTransport.Peek())
-                break;
+                int failureCount = 0;
+                try
+                {
+                    TTransport client = serverTransport.Accept();
+                    lock (clientLock)
+                    {
+                        clientQueue.Enqueue(client);
+                        Monitor.Pulse(clientLock);
+                    }
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        ++failureCount;
+                        logDelegate(ttx.ToString());
+                    }
 
-              //Fire processContext server event
-              //N.B. This is the pattern implemented in C++ and the event fires provisionally.
-              //That is to say it may be many minutes between the event firing and the client request
-              //actually arriving or the client may hang up without ever makeing a request.
-              if (serverEventHandler != null)
-                serverEventHandler.processContext(connectionContext, inputTransport);
-              //Process client request (blocks until transport is readable)
-              if (!processor.Process(inputProtocol, outputProtocol))
-                break;
+                }
             }
-          }
+
+            if (stop)
+            {
+                try
+                {
+                    serverTransport.Close();
+                }
+                catch (TTransportException ttx)
+                {
+                    logDelegate("TServeTransport failed on close: " + ttx.Message);
+                }
+                stop = false;
+            }
         }
-      }
-      catch (TTransportException)
-      {
-        //Usually a client disconnect, expected
-      }
-      catch (Exception x)
-      {
-        //Unexpected
-        logDelegate("Error: " + x);
-      }
 
-      //Fire deleteContext server event after client disconnects
-      if (serverEventHandler != null)
-        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+        /// <summary>
+        /// Loops on processing a client forever
+        /// </summary>
+        private void Execute()
+        {
+            while (!stop)
+            {
+                TTransport client;
+                Thread t;
+                lock (clientLock)
+                {
+                    //don't dequeue if too many connections
+                    while (clientThreads.Count >= maxThreads)
+                    {
+                        Monitor.Wait(clientLock);
+                    }
 
-      lock (clientLock)
-      {
-        clientThreads.Remove(Thread.CurrentThread);
-        Monitor.Pulse(clientLock);
-      }
-      return;
+                    while (clientQueue.Count == 0)
+                    {
+                        Monitor.Wait(clientLock);
+                    }
+
+                    client = clientQueue.Dequeue();
+                    t = new Thread(new ParameterizedThreadStart(ClientWorker));
+                    clientThreads.Add(t);
+                }
+                //start processing requests from client on new thread
+                t.Start(client);
+            }
+        }
+
+        private void ClientWorker(object context)
+        {
+            using (TTransport client = (TTransport)context)
+            {
+                TProcessor processor = processorFactory.GetProcessor(client);
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    try
+                    {
+                        inputTransport = inputTransportFactory.GetTransport(client);
+                        outputTransport = outputTransportFactory.GetTransport(client);
+                        inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                        outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                        //Recover event handler (if any) and fire createContext server event when a client connects
+                        if (serverEventHandler != null)
+                            connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                        //Process client requests until client disconnects
+                        while (!stop)
+                        {
+                            if (!inputTransport.Peek())
+                                break;
+
+                            //Fire processContext server event
+                            //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                            //That is to say it may be many minutes between the event firing and the client request
+                            //actually arriving or the client may hang up without ever makeing a request.
+                            if (serverEventHandler != null)
+                                serverEventHandler.processContext(connectionContext, inputTransport);
+                            //Process client request (blocks until transport is readable)
+                            if (!processor.Process(inputProtocol, outputProtocol))
+                                break;
+                        }
+                    }
+                    catch (TTransportException)
+                    {
+                        //Usually a client disconnect, expected
+                    }
+                    catch (Exception x)
+                    {
+                        //Unexpected
+                        logDelegate("Error: " + x);
+                    }
+
+                    //Fire deleteContext server event after client disconnects
+                    if (serverEventHandler != null)
+                        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+
+                    lock (clientLock)
+                    {
+                        clientThreads.Remove(Thread.CurrentThread);
+                        Monitor.Pulse(clientLock);
+                    }
+
+                }
+                finally
+                {
+                    //Close transports
+                    if (inputTransport != null)
+                        inputTransport.Close();
+                    if (outputTransport != null)
+                        outputTransport.Close();
+
+                    // disposable stuff should be disposed
+                    if (inputProtocol != null)
+                        inputProtocol.Dispose();
+                    if (outputProtocol != null)
+                        outputProtocol.Dispose();
+                }
+            }
+        }
+
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+            //clean up all the threads myself
+            workerThread.Abort();
+            foreach (Thread t in clientThreads)
+            {
+                t.Abort();
+            }
+        }
     }
-
-    public override void Stop()
-    {
-      stop = true;
-      serverTransport.Close();
-      //clean up all the threads myself
-      workerThread.Abort();
-      foreach (Thread t in clientThreads)
-      {
-        t.Abort();
-      }
-    }
-  }
 }
diff --git a/lib/csharp/src/TApplicationException.cs b/lib/csharp/src/TApplicationException.cs
index 4c0d3a3..8dd7ae5 100644
--- a/lib/csharp/src/TApplicationException.cs
+++ b/lib/csharp/src/TApplicationException.cs
@@ -40,7 +40,7 @@
         }
 
         public TApplicationException(ExceptionType type, string message)
-            : base(message)
+            : base(message, null) // TApplicationException is serializable, but we never serialize InnerException
         {
             this.type = type;
         }
@@ -103,7 +103,7 @@
 
             oprot.WriteStructBegin(struc);
 
-            if (!String.IsNullOrEmpty(Message))
+            if (!string.IsNullOrEmpty(Message))
             {
                 field.Name = "message";
                 field.Type = TType.String;
@@ -137,5 +137,10 @@
             InvalidProtocol,
             UnsupportedClientType
         }
+
+        public ExceptionType Type
+        {
+            get { return type; }
+        }
     }
 }
diff --git a/lib/csharp/src/TException.cs b/lib/csharp/src/TException.cs
index 65509ec..aa9a210 100644
--- a/lib/csharp/src/TException.cs
+++ b/lib/csharp/src/TException.cs
@@ -31,8 +31,8 @@
         {
         }
 
-        public TException( string message)
-            : base(message)
+        public TException(string message, Exception inner)
+            : base(message, inner)
         {
         }
 
diff --git a/lib/csharp/src/TPrototypeProcessorFactory.cs b/lib/csharp/src/TPrototypeProcessorFactory.cs
index 6f56d33..0b47261 100644
--- a/lib/csharp/src/TPrototypeProcessorFactory.cs
+++ b/lib/csharp/src/TPrototypeProcessorFactory.cs
@@ -42,7 +42,7 @@
 
         public TProcessor GetProcessor(TTransport trans, TServer server = null)
         {
-            H handler = (H) Activator.CreateInstance(typeof(H), handlerArgs);
+            H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs);
 
             TControllingHandler handlerServerRef = handler as TControllingHandler;
             if (handlerServerRef != null)
diff --git a/lib/csharp/src/TSingletonProcessorFactory.cs b/lib/csharp/src/TSingletonProcessorFactory.cs
index 40dc44c..ed2897b 100644
--- a/lib/csharp/src/TSingletonProcessorFactory.cs
+++ b/lib/csharp/src/TSingletonProcessorFactory.cs
@@ -17,7 +17,7 @@
  * under the License.
  */
 
- using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
diff --git a/lib/csharp/src/Thrift.45.csproj b/lib/csharp/src/Thrift.45.csproj
index 455916f..4e28b25 100644
--- a/lib/csharp/src/Thrift.45.csproj
+++ b/lib/csharp/src/Thrift.45.csproj
@@ -31,7 +31,7 @@
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
     <DefineConstants>TRACE;DEBUG;NET45</DefineConstants>
@@ -39,7 +39,7 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <DefineConstants>TRACE;NET45</DefineConstants>
diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj
index 9040ca5..bf65569 100644
--- a/lib/csharp/src/Thrift.csproj
+++ b/lib/csharp/src/Thrift.csproj
@@ -45,26 +45,27 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
+    <DebugType>portable</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
+    <DefineConstants>
+    </DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
diff --git a/lib/csharp/src/Transport/TBufferedTransport.cs b/lib/csharp/src/Transport/TBufferedTransport.cs
index c969419..8870988 100644
--- a/lib/csharp/src/Transport/TBufferedTransport.cs
+++ b/lib/csharp/src/Transport/TBufferedTransport.cs
@@ -76,19 +76,23 @@
             ValidateBufferArgs(buf, off, len);
             if (!IsOpen)
                 throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+
             if (inputBuffer.Capacity < bufSize)
                 inputBuffer.Capacity = bufSize;
-            int got = inputBuffer.Read(buf, off, len);
-            if (got > 0)
-                return got;
 
-            inputBuffer.Seek(0, SeekOrigin.Begin);
-            inputBuffer.SetLength(inputBuffer.Capacity);
-            int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length);
-            inputBuffer.SetLength(filled);
-            if (filled == 0)
-                return 0;
-            return Read(buf, off, len);
+            while (true)
+            {
+                int got = inputBuffer.Read(buf, off, len);
+                if (got > 0)
+                    return got;
+
+                inputBuffer.Seek(0, SeekOrigin.Begin);
+                inputBuffer.SetLength(inputBuffer.Capacity);
+                int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length);
+                inputBuffer.SetLength(filled);
+                if (filled == 0)
+                    return 0;
+            }
         }
 
         public override void Write(byte[] buf, int off, int len)
@@ -125,9 +129,8 @@
             }
         }
 
-        public override void Flush()
+        private void InternalFlush()
         {
-            CheckNotDisposed();
             if (!IsOpen)
                 throw new TTransportException(TTransportException.ExceptionType.NotOpen);
             if (outputBuffer.Length > 0)
@@ -135,17 +138,39 @@
                 transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length);
                 outputBuffer.SetLength(0);
             }
+        }
+
+        public override void Flush()
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
             transport.Flush();
         }
 
-        private void CheckNotDisposed()
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            return transport.BeginFlush( callback, state);
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            transport.EndFlush( asyncResult);
+        }
+
+
+
+        protected void CheckNotDisposed()
         {
             if (_IsDisposed)
                 throw new ObjectDisposedException("TBufferedTransport");
         }
 
         #region " IDisposable Support "
-        private bool _IsDisposed;
+        protected bool _IsDisposed { get; private set; }
 
         // IDisposable
         protected override void Dispose(bool disposing)
@@ -154,11 +179,11 @@
             {
                 if (disposing)
                 {
-                    if(inputBuffer != null)
+                    if (inputBuffer != null)
                         inputBuffer.Dispose();
-                    if(outputBuffer != null)
+                    if (outputBuffer != null)
                         outputBuffer.Dispose();
-                    if(transport != null)
+                    if (transport != null)
                         transport.Dispose();
                 }
             }
diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs
index 0af8b1f..a746a32 100644
--- a/lib/csharp/src/Transport/TFramedTransport.cs
+++ b/lib/csharp/src/Transport/TFramedTransport.cs
@@ -108,7 +108,7 @@
             writeBuffer.Write(buf, off, len);
         }
 
-        public override void Flush()
+        private void InternalFlush()
         {
             CheckNotDisposed();
             if (!IsOpen)
@@ -116,8 +116,8 @@
             byte[] buf = writeBuffer.GetBuffer();
             int len = (int)writeBuffer.Length;
             int data_len = len - HeaderSize;
-            if ( data_len < 0 )
-                throw new System.InvalidOperationException (); // logic error actually
+            if (data_len < 0)
+                throw new System.InvalidOperationException(); // logic error actually
 
             // Inject message header into the reserved buffer space
             EncodeFrameSize(data_len, buf);
@@ -126,11 +126,30 @@
             transport.Write(buf, 0, len);
 
             InitWriteBuffer();
+        }
+
+        public override void Flush()
+        {
+            CheckNotDisposed();
+            InternalFlush();
 
             transport.Flush();
         }
 
-        private void InitWriteBuffer ()
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            return transport.BeginFlush( callback, state);
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            transport.EndFlush( asyncResult);
+        }
+
+        private void InitWriteBuffer()
         {
             // Reserve space for message header to be put right before sending it out
             writeBuffer.SetLength(HeaderSize);
@@ -150,7 +169,7 @@
             return
                 ((buf[0] & 0xff) << 24) |
                 ((buf[1] & 0xff) << 16) |
-                ((buf[2] & 0xff) <<  8) |
+                ((buf[2] & 0xff) << 8) |
                 ((buf[3] & 0xff));
         }
 
@@ -171,11 +190,11 @@
             {
                 if (disposing)
                 {
-                    if(readBuffer != null)
+                    if (readBuffer != null)
                         readBuffer.Dispose();
-                    if(writeBuffer != null)
+                    if (writeBuffer != null)
                         writeBuffer.Dispose();
-                    if(transport != null)
+                    if (transport != null)
                         transport.Dispose();
                 }
             }
diff --git a/lib/csharp/src/Transport/THttpClient.cs b/lib/csharp/src/Transport/THttpClient.cs
index f678d1e..667fc25 100644
--- a/lib/csharp/src/Transport/THttpClient.cs
+++ b/lib/csharp/src/Transport/THttpClient.cs
@@ -30,7 +30,6 @@
 
 namespace Thrift.Transport
 {
-
     public class THttpClient : TTransport, IDisposable
     {
         private readonly Uri uri;
@@ -43,7 +42,7 @@
 
         private int readTimeout = 30000;
 
-        private IDictionary<String, String> customHeaders = new Dictionary<string, string>();
+        private IDictionary<string, string> customHeaders = new Dictionary<string, string>();
 
 #if !SILVERLIGHT
         private IWebProxy proxy = WebRequest.DefaultWebProxy;
@@ -64,7 +63,7 @@
         {
             set
             {
-               connectTimeout = value;
+                connectTimeout = value;
             }
         }
 
@@ -76,7 +75,7 @@
             }
         }
 
-        public IDictionary<String, String> CustomHeaders
+        public IDictionary<string, string> CustomHeaders
         {
             get
             {
@@ -140,7 +139,7 @@
             }
             catch (IOException iox)
             {
-                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString());
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox);
             }
         }
 
@@ -218,11 +217,11 @@
             }
             catch (IOException iox)
             {
-                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString());
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox);
             }
             catch (WebException wx)
             {
-                throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx);
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx, wx);
             }
         }
 
@@ -317,7 +316,7 @@
             }
             catch (IOException iox)
             {
-                throw new TTransportException(iox.ToString());
+                throw new TTransportException(iox.ToString(), iox);
             }
         }
 
@@ -325,7 +324,7 @@
         {
             try
             {
-                var flushAsyncResult = (FlushAsyncResult) asyncResult;
+                var flushAsyncResult = (FlushAsyncResult)asyncResult;
 
                 if (!flushAsyncResult.IsCompleted)
                 {
@@ -338,7 +337,8 @@
                 {
                     throw flushAsyncResult.AsyncException;
                 }
-            } finally
+            }
+            finally
             {
                 outputStream = new MemoryStream();
             }
@@ -360,7 +360,7 @@
             }
             catch (Exception exception)
             {
-                flushAsyncResult.AsyncException = new TTransportException(exception.ToString());
+                flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception);
                 flushAsyncResult.UpdateStatusToComplete();
                 flushAsyncResult.NotifyCallbackWhenAvailable();
             }
@@ -375,7 +375,7 @@
             }
             catch (Exception exception)
             {
-                flushAsyncResult.AsyncException = new TTransportException(exception.ToString());
+                flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception);
             }
             flushAsyncResult.UpdateStatusToComplete();
             flushAsyncResult.NotifyCallbackWhenAvailable();
@@ -387,9 +387,9 @@
             private volatile Boolean _isCompleted;
             private ManualResetEvent _evt;
             private readonly AsyncCallback _cbMethod;
-            private readonly Object _state;
+            private readonly object _state;
 
-            public FlushAsyncResult(AsyncCallback cbMethod, Object state)
+            public FlushAsyncResult(AsyncCallback cbMethod, object state)
             {
                 _cbMethod = cbMethod;
                 _state = state;
@@ -415,7 +415,7 @@
             {
                 get { return _isCompleted; }
             }
-            private readonly Object _locker = new Object();
+            private readonly object _locker = new object();
             private ManualResetEvent GetEvtHandle()
             {
                 lock (_locker)
@@ -452,7 +452,7 @@
             }
         }
 
-#region " IDisposable Support "
+        #region " IDisposable Support "
         private bool _IsDisposed;
 
         // IDisposable
@@ -470,6 +470,6 @@
             }
             _IsDisposed = true;
         }
-#endregion
+        #endregion
     }
 }
diff --git a/lib/csharp/src/Transport/TMemoryBuffer.cs b/lib/csharp/src/Transport/TMemoryBuffer.cs
index d8ff9dc..303d083 100644
--- a/lib/csharp/src/Transport/TMemoryBuffer.cs
+++ b/lib/csharp/src/Transport/TMemoryBuffer.cs
@@ -22,45 +22,56 @@
 using System.Reflection;
 using Thrift.Protocol;
 
-namespace Thrift.Transport {
-    public class TMemoryBuffer : TTransport {
+namespace Thrift.Transport
+{
+    public class TMemoryBuffer : TTransport
+    {
 
         private readonly MemoryStream byteStream;
 
-        public TMemoryBuffer() {
+        public TMemoryBuffer()
+        {
             byteStream = new MemoryStream();
         }
 
-        public TMemoryBuffer(byte[] buf) {
+        public TMemoryBuffer(byte[] buf)
+        {
             byteStream = new MemoryStream(buf);
         }
 
-        public override void Open() {
+        public override void Open()
+        {
             /** do nothing **/
         }
 
-        public override void Close() {
+        public override void Close()
+        {
             /** do nothing **/
         }
 
-        public override int Read(byte[] buf, int off, int len) {
+        public override int Read(byte[] buf, int off, int len)
+        {
             return byteStream.Read(buf, off, len);
         }
 
-        public override void Write(byte[] buf, int off, int len) {
+        public override void Write(byte[] buf, int off, int len)
+        {
             byteStream.Write(buf, off, len);
         }
 
-        public byte[] GetBuffer() {
+        public byte[] GetBuffer()
+        {
             return byteStream.ToArray();
         }
 
 
-        public override bool IsOpen {
+        public override bool IsOpen
+        {
             get { return true; }
         }
 
-        public static byte[] Serialize(TAbstractBase s) {
+        public static byte[] Serialize(TAbstractBase s)
+        {
             var t = new TMemoryBuffer();
             var p = new TBinaryProtocol(t);
 
@@ -69,26 +80,33 @@
             return t.GetBuffer();
         }
 
-        public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase {
+        public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase
+        {
             var trans = new TMemoryBuffer(buf);
             var p = new TBinaryProtocol(trans);
-            if (typeof (TBase).IsAssignableFrom(typeof (T))) {
-                var method = typeof (T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
+            if (typeof(TBase).IsAssignableFrom(typeof(T)))
+            {
+                var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
                 var t = Activator.CreateInstance<T>();
-                method.Invoke(t, new object[] {p});
+                method.Invoke(t, new object[] { p });
                 return t;
-             } else {
-                   var method = typeof (T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
-                return (T) method.Invoke(null, new object[] {p});
+            }
+            else
+            {
+                var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
+                return (T)method.Invoke(null, new object[] { p });
             }
         }
 
         private bool _IsDisposed;
 
         // IDisposable
-        protected override void Dispose(bool disposing) {
-            if (!_IsDisposed) {
-                if (disposing) {
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
                     if (byteStream != null)
                         byteStream.Dispose();
                 }
@@ -96,4 +114,4 @@
             _IsDisposed = true;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/csharp/src/Transport/TNamedPipeClientTransport.cs b/lib/csharp/src/Transport/TNamedPipeClientTransport.cs
index ea2e862..49a50aa 100644
--- a/lib/csharp/src/Transport/TNamedPipeClientTransport.cs
+++ b/lib/csharp/src/Transport/TNamedPipeClientTransport.cs
@@ -108,4 +108,4 @@
             client.Dispose();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/csharp/src/Transport/TNamedPipeServerTransport.cs b/lib/csharp/src/Transport/TNamedPipeServerTransport.cs
index a6cfb2e..32215cf 100644
--- a/lib/csharp/src/Transport/TNamedPipeServerTransport.cs
+++ b/lib/csharp/src/Transport/TNamedPipeServerTransport.cs
@@ -130,7 +130,7 @@
                             if (stream != null)
                                 eOuter = e;
                             else
-                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message);
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
                         }
                         evt.Set();
                     }, null);
@@ -157,7 +157,7 @@
             catch (Exception e)
             {
                 Close();
-                throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message);
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message, e);
             }
         }
 
@@ -214,7 +214,7 @@
                             if (stream != null)
                                 eOuter = e;
                             else
-                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message);
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
                         }
                         evt.Set();
                     }, null);
@@ -265,7 +265,7 @@
                                 if (stream != null)
                                     eOuter = e;
                                 else
-                                    eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message);
+                                    eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
                             }
                             evt.Set();
                         }, null);
diff --git a/lib/csharp/src/Transport/TServerSocket.cs b/lib/csharp/src/Transport/TServerSocket.cs
index e29a87e..d8ec62a 100644
--- a/lib/csharp/src/Transport/TServerSocket.cs
+++ b/lib/csharp/src/Transport/TServerSocket.cs
@@ -27,150 +27,150 @@
 
 namespace Thrift.Transport
 {
-	public class TServerSocket : TServerTransport
-	{
-        /**
-        * Underlying server with socket
-        */
-		private TcpListener server = null;
+    public class TServerSocket : TServerTransport
+    {
+        /// <summary>
+        /// Underlying server with socket.
+        /// </summary>
+        private TcpListener server = null;
 
-		/**
-		 * Port to listen on
-		 */
-		private int port = 0;
+        /// <summary>
+        /// Port to listen on.
+        /// </summary>
+        private int port = 0;
 
-		/**
-		 * Timeout for client sockets from accept
-		 */
-		private int clientTimeout = 0;
+        /// <summary>
+        /// Timeout for client sockets from accept.
+        /// </summary>
+        private int clientTimeout = 0;
 
-		/**
-		 * Whether or not to wrap new TSocket connections in buffers
-		 */
-		private bool useBufferedSockets = false;
+        /// <summary>
+        /// Whether or not to wrap new TSocket connections in buffers.
+        /// </summary>
+        private bool useBufferedSockets = false;
 
-		/**
-		 * Creates a server socket from underlying socket object
-		 */
-		public TServerSocket(TcpListener listener)
-            :this(listener, 0)
-		{
-		}
+        /// <summary>
+        /// Creates a server socket from underlying socket object.
+        /// </summary>
+        public TServerSocket(TcpListener listener)
+            : this(listener, 0)
+        {
+        }
 
-		/**
-		 * Creates a server socket from underlying socket object
-		 */
-		public TServerSocket(TcpListener listener, int clientTimeout)
-		{
-			this.server = listener;
-			this.clientTimeout = clientTimeout;
-		}
+        /// <summary>
+        /// Creates a server socket from underlying socket object.
+        /// </summary>
+        public TServerSocket(TcpListener listener, int clientTimeout)
+        {
+            this.server = listener;
+            this.clientTimeout = clientTimeout;
+        }
 
-		/**
-		 * Creates just a port listening server socket
-		 */
-		public TServerSocket(int port)
-			: this(port, 0)
-		{
-		}
+        /// <summary>
+        /// Creates just a port listening server socket.
+        /// </summary>
+        public TServerSocket(int port)
+            : this(port, 0)
+        {
+        }
 
-		/**
-		 * Creates just a port listening server socket
-		 */
-		public TServerSocket(int port, int clientTimeout)
-            :this(port, clientTimeout, false)
-		{
-		}
+        /// <summary>
+        /// Creates just a port listening server socket.
+        /// </summary>
+        public TServerSocket(int port, int clientTimeout)
+            : this(port, clientTimeout, false)
+        {
+        }
 
-		public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
-		{
-			this.port = port;
-			this.clientTimeout = clientTimeout;
-			this.useBufferedSockets = useBufferedSockets;
-			try
-			{
-				// Make server socket
-				this.server = TSocketVersionizer.CreateTcpListener(this.port);
-				this.server.Server.NoDelay = true;
-			}
-			catch (Exception)
-			{
-				server = null;
-				throw new TTransportException("Could not create ServerSocket on port " + this.port + ".");
-			}
-		}
+        public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
+        {
+            this.port = port;
+            this.clientTimeout = clientTimeout;
+            this.useBufferedSockets = useBufferedSockets;
+            try
+            {
+                // Make server socket
+                this.server = TSocketVersionizer.CreateTcpListener(this.port);
+                this.server.Server.NoDelay = true;
+            }
+            catch (Exception ex)
+            {
+                server = null;
+                throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex);
+            }
+        }
 
-		public override void Listen()
-		{
-			// Make sure not to block on accept
-			if (server != null)
-			{
-				try
-				{
-					server.Start();
-				}
-				catch (SocketException sx)
-				{
-					throw new TTransportException("Could not accept on listening socket: " + sx.Message);
-				}
-			}
-		}
+        public override void Listen()
+        {
+            // Make sure not to block on accept
+            if (server != null)
+            {
+                try
+                {
+                    server.Start();
+                }
+                catch (SocketException sx)
+                {
+                    throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx);
+                }
+            }
+        }
 
-		protected override TTransport AcceptImpl()
-		{
-			if (server == null)
-			{
-				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
-			}
-			try
-			{
-				TSocket result2 = null;
-				TcpClient result = server.AcceptTcpClient();
-				try
-				{
-					result2 = new TSocket(result);
-					result2.Timeout = clientTimeout;
-					if (useBufferedSockets)
-					{
-						TBufferedTransport result3 = new TBufferedTransport(result2);
-						return result3;
-					}
-					else
-					{
-						return result2;
-					}
-				}
-				catch (System.Exception)
-				{
-					// If a TSocket was successfully created, then let
-					// it do proper cleanup of the TcpClient object.
-					if (result2 != null)
-						result2.Dispose();
-					else //  Otherwise, clean it up ourselves.
-						((IDisposable)result).Dispose();
-					throw;
-				}
-			}
-			catch (Exception ex)
-			{
-				throw new TTransportException(ex.ToString());
-			}
-		}
+        protected override TTransport AcceptImpl()
+        {
+            if (server == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
+            }
+            try
+            {
+                TSocket result2 = null;
+                TcpClient result = server.AcceptTcpClient();
+                try
+                {
+                    result2 = new TSocket(result);
+                    result2.Timeout = clientTimeout;
+                    if (useBufferedSockets)
+                    {
+                        TBufferedTransport result3 = new TBufferedTransport(result2);
+                        return result3;
+                    }
+                    else
+                    {
+                        return result2;
+                    }
+                }
+                catch (System.Exception)
+                {
+                    // If a TSocket was successfully created, then let
+                    // it do proper cleanup of the TcpClient object.
+                    if (result2 != null)
+                        result2.Dispose();
+                    else //  Otherwise, clean it up ourselves.
+                        ((IDisposable)result).Dispose();
+                    throw;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new TTransportException(ex.ToString(), ex);
+            }
+        }
 
-		public override void Close()
-		{
-			if (server != null)
-			{
-				try
-				{
-					server.Stop();
-				}
-				catch (Exception ex)
-				{
-					throw new TTransportException("WARNING: Could not close server socket: " + ex);
-				}
-				server = null;
-			}
-		}
-	}
+        public override void Close()
+        {
+            if (server != null)
+            {
+                try
+                {
+                    server.Stop();
+                }
+                catch (Exception ex)
+                {
+                    throw new TTransportException("WARNING: Could not close server socket: " + ex, ex);
+                }
+                server = null;
+            }
+        }
+    }
 }
diff --git a/lib/csharp/src/Transport/TServerTransport.cs b/lib/csharp/src/Transport/TServerTransport.cs
index 05d7d0f..e63880b 100644
--- a/lib/csharp/src/Transport/TServerTransport.cs
+++ b/lib/csharp/src/Transport/TServerTransport.cs
@@ -34,10 +34,11 @@
         public TTransport Accept()
         {
             TTransport transport = AcceptImpl();
-            if (transport == null) {
-              throw new TTransportException("accept() may not return NULL");
+            if (transport == null)
+            {
+                throw new TTransportException("accept() may not return NULL");
             }
             return transport;
-         }
+        }
     }
 }
diff --git a/lib/csharp/src/Transport/TSilverlightSocket.cs b/lib/csharp/src/Transport/TSilverlightSocket.cs
index cbd3baa..40469ab 100644
--- a/lib/csharp/src/Transport/TSilverlightSocket.cs
+++ b/lib/csharp/src/Transport/TSilverlightSocket.cs
@@ -112,7 +112,7 @@
                 throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
             }
 
-            if (String.IsNullOrEmpty(host))
+            if (string.IsNullOrEmpty(host))
             {
                 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
             }
@@ -282,9 +282,9 @@
             private volatile Boolean _isCompleted;
             private ManualResetEvent _evt;
             private readonly AsyncCallback _cbMethod;
-            private readonly Object _state;
+            private readonly object _state;
 
-            public FlushAsyncResult(AsyncCallback cbMethod, Object state)
+            public FlushAsyncResult(AsyncCallback cbMethod, object state)
             {
                 _cbMethod = cbMethod;
                 _state = state;
@@ -314,7 +314,7 @@
                 get { return _isCompleted; }
             }
 
-            private readonly Object _locker = new Object();
+            private readonly object _locker = new object();
 
             private ManualResetEvent GetEvtHandle()
             {
@@ -362,7 +362,7 @@
             }
         }
 
-        #region " IDisposable Support "
+#region " IDisposable Support "
         private bool _IsDisposed;
 
         // IDisposable
@@ -385,7 +385,7 @@
             }
             _IsDisposed = true;
         }
-        #endregion
+#endregion
     }
 }
 
diff --git a/lib/csharp/src/Transport/TSocket.cs b/lib/csharp/src/Transport/TSocket.cs
index 7501e30..d8fa335 100644
--- a/lib/csharp/src/Transport/TSocket.cs
+++ b/lib/csharp/src/Transport/TSocket.cs
@@ -26,216 +26,220 @@
 
 namespace Thrift.Transport
 {
-	public class TSocket : TStreamTransport
-	{
-		private TcpClient client = null;
-		private string host = null;
-		private int port = 0;
-		private int timeout = 0;
+    public class TSocket : TStreamTransport
+    {
+        private TcpClient client = null;
+        private string host = null;
+        private int port = 0;
+        private int timeout = 0;
 
-		public TSocket(TcpClient client)
-		{
-			this.client = client;
+        public TSocket(TcpClient client)
+        {
+            this.client = client;
 
-			if (IsOpen)
-			{
-				inputStream = client.GetStream();
-				outputStream = client.GetStream();
-			}
-		}
+            if (IsOpen)
+            {
+                inputStream = client.GetStream();
+                outputStream = client.GetStream();
+            }
+        }
 
-		public TSocket(string host, int port)
-			: this(host, port, 0)
-		{
-		}
+        public TSocket(string host, int port)
+            : this(host, port, 0)
+        {
+        }
 
-		public TSocket(string host, int port, int timeout)
-		{
-			this.host = host;
-			this.port = port;
-			this.timeout = timeout;
+        public TSocket(string host, int port, int timeout)
+        {
+            this.host = host;
+            this.port = port;
+            this.timeout = timeout;
 
-			InitSocket();
-		}
+            InitSocket();
+        }
 
-		private void InitSocket()
-		{
-			this.client = TSocketVersionizer.CreateTcpClient();
-			this.client.ReceiveTimeout = client.SendTimeout = timeout;
-			this.client.Client.NoDelay = true;
-		}
+        private void InitSocket()
+        {
+            this.client = TSocketVersionizer.CreateTcpClient();
+            this.client.ReceiveTimeout = client.SendTimeout = timeout;
+            this.client.Client.NoDelay = true;
+        }
 
-		public int Timeout
-		{
-			set
-			{
-				client.ReceiveTimeout = client.SendTimeout = timeout = value;
-			}
-		}
+        public int Timeout
+        {
+            set
+            {
+                client.ReceiveTimeout = client.SendTimeout = timeout = value;
+            }
+        }
 
-		public TcpClient TcpClient
-		{
-			get
-			{
-				return client;
-			}
-		}
+        public TcpClient TcpClient
+        {
+            get
+            {
+                return client;
+            }
+        }
 
-		public string Host
-		{
-			get
-			{
-				return host;
-			}
-		}
+        public string Host
+        {
+            get
+            {
+                return host;
+            }
+        }
 
-		public int Port
-		{
-			get
-			{
-				return port;
-			}
-		}
+        public int Port
+        {
+            get
+            {
+                return port;
+            }
+        }
 
-		public override bool IsOpen
-		{
-			get
-			{
-				if (client == null)
-				{
-					return false;
-				}
+        public override bool IsOpen
+        {
+            get
+            {
+                if (client == null)
+                {
+                    return false;
+                }
 
-				return client.Connected;
-			}
-		}
+                return client.Connected;
+            }
+        }
 
-		public override void Open()
-		{
-			if (IsOpen)
-			{
-				throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
-			}
+        public override void Open()
+        {
+            if (IsOpen)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
+            }
 
-			if (String.IsNullOrEmpty(host))
-			{
-				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
-			}
+            if (string.IsNullOrEmpty(host))
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
+            }
 
-			if (port <= 0)
-			{
-				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
-			}
+            if (port <= 0)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
+            }
 
-			if (client == null)
-			{
-				InitSocket();
-			}
+            if (client == null)
+            {
+                InitSocket();
+            }
 
-            if( timeout == 0)            // no timeout -> infinite
-			{
-				client.Connect(host, port);
-			}
-			else                        // we have a timeout -> use it
-			{
-				ConnectHelper hlp = new ConnectHelper(client);
-				IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
-				bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
-				if (!bConnected)
-				{
-					lock (hlp.Mutex)
-					{
-                        if( hlp.CallbackDone)
-						{
-							asyncres.AsyncWaitHandle.Close();
-							client.Close();
-						}
-						else
-						{
-							hlp.DoCleanup = true;
-							client = null;
-						}
-					}
-					throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
-				}
-			}
+            if (timeout == 0)            // no timeout -> infinite
+            {
+                client.Connect(host, port);
+            }
+            else                        // we have a timeout -> use it
+            {
+                ConnectHelper hlp = new ConnectHelper(client);
+                IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
+                bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
+                if (!bConnected)
+                {
+                    lock (hlp.Mutex)
+                    {
+                        if (hlp.CallbackDone)
+                        {
+                            asyncres.AsyncWaitHandle.Close();
+                            client.Close();
+                        }
+                        else
+                        {
+                            hlp.DoCleanup = true;
+                            client = null;
+                        }
+                    }
+                    throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
+                }
+            }
 
-			inputStream = client.GetStream();
-			outputStream = client.GetStream();
-		}
+            inputStream = client.GetStream();
+            outputStream = client.GetStream();
+        }
 
 
-		static void ConnectCallback(IAsyncResult asyncres)
-		{
-			ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
-			lock (hlp.Mutex)
-			{
-				hlp.CallbackDone = true;
+        static void ConnectCallback(IAsyncResult asyncres)
+        {
+            ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
+            lock (hlp.Mutex)
+            {
+                hlp.CallbackDone = true;
 
-				try
-				{
-                    if( hlp.Client.Client != null)
-						hlp.Client.EndConnect(asyncres);
-				}
-				catch (Exception)
-				{
-					// catch that away
-				}
+                try
+                {
+                    if (hlp.Client.Client != null)
+                        hlp.Client.EndConnect(asyncres);
+                }
+                catch (Exception)
+                {
+                    // catch that away
+                }
 
-				if (hlp.DoCleanup)
-				{
-                    try {
-						asyncres.AsyncWaitHandle.Close();
-                    } catch (Exception) {}
+                if (hlp.DoCleanup)
+                {
+                    try
+                    {
+                        asyncres.AsyncWaitHandle.Close();
+                    }
+                    catch (Exception) { }
 
-                    try {
-						if (hlp.Client is IDisposable)
-							((IDisposable)hlp.Client).Dispose();
-                    } catch (Exception) {}
-					hlp.Client = null;
-				}
-			}
-		}
+                    try
+                    {
+                        if (hlp.Client is IDisposable)
+                            ((IDisposable)hlp.Client).Dispose();
+                    }
+                    catch (Exception) { }
+                    hlp.Client = null;
+                }
+            }
+        }
 
-		private class ConnectHelper
-		{
-			public object Mutex = new object();
-			public bool DoCleanup = false;
-			public bool CallbackDone = false;
-			public TcpClient Client;
-			public ConnectHelper(TcpClient client)
-			{
-				Client = client;
-			}
-		}
+        private class ConnectHelper
+        {
+            public object Mutex = new object();
+            public bool DoCleanup = false;
+            public bool CallbackDone = false;
+            public TcpClient Client;
+            public ConnectHelper(TcpClient client)
+            {
+                Client = client;
+            }
+        }
 
-		public override void Close()
-		{
-			base.Close();
-			if (client != null)
-			{
-				client.Close();
-				client = null;
-			}
-		}
+        public override void Close()
+        {
+            base.Close();
+            if (client != null)
+            {
+                client.Close();
+                client = null;
+            }
+        }
 
-		#region " IDisposable Support "
-		private bool _IsDisposed;
+        #region " IDisposable Support "
+        private bool _IsDisposed;
 
-		// IDisposable
-		protected override void Dispose(bool disposing)
-		{
-			if (!_IsDisposed)
-			{
-				if (disposing)
-				{
-					if (client != null)
-						((IDisposable)client).Dispose();
-					base.Dispose(disposing);
-				}
-			}
-			_IsDisposed = true;
-		}
-		#endregion
-	}
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (client != null)
+                        ((IDisposable)client).Dispose();
+                    base.Dispose(disposing);
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
 }
diff --git a/lib/csharp/src/Transport/TSocketVersionizer.cs b/lib/csharp/src/Transport/TSocketVersionizer.cs
index 904e519..bf4c0e4 100644
--- a/lib/csharp/src/Transport/TSocketVersionizer.cs
+++ b/lib/csharp/src/Transport/TSocketVersionizer.cs
@@ -1,4 +1,27 @@
-using System;
+/**
+ * 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.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net.Sockets;
@@ -10,46 +33,46 @@
 
 namespace Thrift.Transport
 {
-	/**
-	* PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
-	* automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
-	* If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
-	*/
-	internal static class TSocketVersionizer
-	{
-		/*
-		* Creates a TcpClient according to the capabilitites of the used framework
-		*/
-		internal static TcpClient CreateTcpClient()
-		{
-			TcpClient client = null;
+    /// <summary>
+    /// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
+    /// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
+    /// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
+    /// </summary>
+    internal static class TSocketVersionizer
+    {
+        /// <summary>
+        /// Creates a TcpClient according to the capabilitites of the used framework
+        /// </summary>
+        internal static TcpClient CreateTcpClient()
+        {
+            TcpClient client = null;
 
 #if NET45
-			client = new TcpClient(AddressFamily.InterNetworkV6);
-			client.Client.DualMode = true;
+            client = new TcpClient(AddressFamily.InterNetworkV6);
+            client.Client.DualMode = true;
 #else
             client = new TcpClient(AddressFamily.InterNetwork);
 #endif
 
-			return client;
-		}
+            return client;
+        }
 
-		/*
-		* Creates a TcpListener according to the capabilitites of the used framework
-		*/
-		internal static TcpListener CreateTcpListener(Int32 port)
-		{
-			TcpListener listener = null;
+        /// <summary>
+        /// Creates a TcpListener according to the capabilitites of the used framework.
+        /// </summary>
+        internal static TcpListener CreateTcpListener(Int32 port)
+        {
+            TcpListener listener = null;
 
 #if NET45
-			listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
-			listener.Server.DualMode = true;
+            listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
+            listener.Server.DualMode = true;
 #else
 
-			listener = new TcpListener(System.Net.IPAddress.Any, port);
+            listener = new TcpListener(System.Net.IPAddress.Any, port);
 #endif
 
             return listener;
-		}
-	}
+        }
+    }
 }
diff --git a/lib/csharp/src/Transport/TStreamTransport.cs b/lib/csharp/src/Transport/TStreamTransport.cs
index 468743c..304599f 100644
--- a/lib/csharp/src/Transport/TStreamTransport.cs
+++ b/lib/csharp/src/Transport/TStreamTransport.cs
@@ -105,24 +105,24 @@
         }
 
 
-    #region " IDisposable Support "
-    private bool _IsDisposed;
+        #region " IDisposable Support "
+        private bool _IsDisposed;
 
-    // IDisposable
-    protected override void Dispose(bool disposing)
-    {
-      if (!_IsDisposed)
-      {
-        if (disposing)
+        // IDisposable
+        protected override void Dispose(bool disposing)
         {
-          if (InputStream != null)
-            InputStream.Dispose();
-          if (OutputStream != null)
-            OutputStream.Dispose();
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (InputStream != null)
+                        InputStream.Dispose();
+                    if (OutputStream != null)
+                        OutputStream.Dispose();
+                }
+            }
+            _IsDisposed = true;
         }
-      }
-      _IsDisposed = true;
+        #endregion
     }
-    #endregion
-  }
 }
diff --git a/lib/csharp/src/Transport/TTLSServerSocket.cs b/lib/csharp/src/Transport/TTLSServerSocket.cs
index 24222b7..716a97c 100644
--- a/lib/csharp/src/Transport/TTLSServerSocket.cs
+++ b/lib/csharp/src/Transport/TTLSServerSocket.cs
@@ -76,7 +76,7 @@
         /// <param name="port">The port where the server runs.</param>
         /// <param name="certificate">The certificate object.</param>
         public TTLSServerSocket(int port, X509Certificate2 certificate)
-            : this(port,  0, certificate)
+            : this(port, 0, certificate)
         {
         }
 
@@ -129,10 +129,10 @@
                 this.server = TSocketVersionizer.CreateTcpListener(this.port);
                 this.server.Server.NoDelay = true;
             }
-            catch (Exception)
+            catch (Exception ex)
             {
                 server = null;
-                throw new TTransportException("Could not create ServerSocket on port " + this.port + ".");
+                throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex);
             }
         }
 
@@ -150,7 +150,7 @@
                 }
                 catch (SocketException sx)
                 {
-                    throw new TTransportException("Could not accept on listening socket: " + sx.Message);
+                    throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx);
                 }
             }
         }
@@ -197,7 +197,7 @@
             }
             catch (Exception ex)
             {
-                throw new TTransportException(ex.ToString());
+                throw new TTransportException(ex.ToString(), ex);
             }
         }
 
@@ -214,7 +214,7 @@
                 }
                 catch (Exception ex)
                 {
-                    throw new TTransportException("WARNING: Could not close server socket: " + ex);
+                    throw new TTransportException("WARNING: Could not close server socket: " + ex, ex);
                 }
                 this.server = null;
             }
diff --git a/lib/csharp/src/Transport/TTLSSocket.cs b/lib/csharp/src/Transport/TTLSSocket.cs
index 27be0f4..fd019c3 100644
--- a/lib/csharp/src/Transport/TTLSSocket.cs
+++ b/lib/csharp/src/Transport/TTLSSocket.cs
@@ -263,7 +263,7 @@
         /// <param name="sender">The sender-object.</param>
         /// <param name="certificate">The used certificate.</param>
         /// <param name="chain">The certificate chain.</param>
-        /// <param name="sslPolicyErrors">An enum, which lists all the errors from the .NET certificate check.</param>
+        /// <param name="sslValidationErrors">An enum, which lists all the errors from the .NET certificate check.</param>
         /// <returns></returns>
         private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors)
         {
@@ -280,7 +280,7 @@
                 throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
             }
 
-            if (String.IsNullOrEmpty(host))
+            if (string.IsNullOrEmpty(host))
             {
                 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
             }
@@ -307,7 +307,7 @@
         {
             RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator;
 
-            if( this.localCertificateSelectionCallback != null)
+            if (this.localCertificateSelectionCallback != null)
             {
                 this.secureStream = new SslStream(
                     this.client.GetStream(),
@@ -335,7 +335,7 @@
                 else
                 {
                     // Client authentication
-                    X509CertificateCollection certs = certificate != null ?  new X509CertificateCollection { certificate } : new X509CertificateCollection();
+                    X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
                     this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true);
                 }
             }
diff --git a/lib/csharp/src/Transport/TTransport.cs b/lib/csharp/src/Transport/TTransport.cs
index 6fb1077..5e4ac22 100644
--- a/lib/csharp/src/Transport/TTransport.cs
+++ b/lib/csharp/src/Transport/TTransport.cs
@@ -53,7 +53,7 @@
                 if (bytes == 0)
                     return false;
             }
-            catch( IOException)
+            catch (IOException)
             {
                 return false;
             }
@@ -108,7 +108,7 @@
 
         public virtual void Write(byte[] buf)
         {
-            Write (buf, 0, buf.Length);
+            Write(buf, 0, buf.Length);
         }
 
         public abstract void Write(byte[] buf, int off, int len);
diff --git a/lib/csharp/src/Transport/TTransportException.cs b/lib/csharp/src/Transport/TTransportException.cs
index ae987d5..7f6cc18 100644
--- a/lib/csharp/src/Transport/TTransportException.cs
+++ b/lib/csharp/src/Transport/TTransportException.cs
@@ -40,14 +40,14 @@
             this.type = type;
         }
 
-        public TTransportException(ExceptionType type, string message)
-            : base(message)
+        public TTransportException(ExceptionType type, string message, Exception inner = null)
+            : base(message, inner)
         {
             this.type = type;
         }
 
-        public TTransportException(string message)
-            : base(message)
+        public TTransportException(string message, Exception inner = null)
+            : base(message, inner)
         {
         }
 
diff --git a/lib/csharp/src/Transport/TTransportFactory.cs b/lib/csharp/src/Transport/TTransportFactory.cs
index fa10033..47a0c62 100644
--- a/lib/csharp/src/Transport/TTransportFactory.cs
+++ b/lib/csharp/src/Transport/TTransportFactory.cs
@@ -26,7 +26,7 @@
 namespace Thrift.Transport
 {
     /// <summary>
-    /// From Mark Slee & Aditya Agarwal of Facebook:
+    /// From Mark Slee &amp; Aditya Agarwal of Facebook:
     /// Factory class used to create wrapped instance of Transports.
     /// This is used primarily in servers, which get Transports from
     /// a ServerTransport and then may want to mutate them (i.e. create
diff --git a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs
index fe0c46b..fdff4a1 100644
--- a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs
+++ b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
 // übernehmen, indem Sie "*" eingeben:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
index ed9616b..21e1ce1 100644
--- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
+++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
@@ -46,7 +46,7 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
@@ -145,4 +145,4 @@
 
 </PreBuildEvent>
   </PropertyGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
index e2d433e..f686ded 100644
--- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
+++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
index e0ca45c..c4a4394 100644
--- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
+++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
@@ -46,7 +46,7 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
@@ -145,4 +145,4 @@
 
 </PreBuildEvent>
   </PropertyGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
index 8f63d65..5d40546 100644
--- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
+++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs
index 8acb1c2..cfe8894 100644
--- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs
+++ b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs
@@ -49,5 +49,5 @@
 //
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
-[assembly: AssemblyVersion("0.11.0.1")]
-[assembly: AssemblyFileVersion("0.11.0.1")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/d/src/thrift/async/socket.d b/lib/d/src/thrift/async/socket.d
index 6de13d9..a08f51d 100644
--- a/lib/d/src/thrift/async/socket.d
+++ b/lib/d/src/thrift/async/socket.d
@@ -18,6 +18,7 @@
  */
 module thrift.async.socket;
 
+import core.stdc.errno: ECONNRESET;
 import core.thread : Fiber;
 import core.time : dur, Duration;
 import std.array : empty;
diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d
index 8aea536..d5ece73 100644
--- a/lib/d/src/thrift/base.d
+++ b/lib/d/src/thrift/base.d
@@ -50,7 +50,7 @@
 /// The Thrift version string, used for informative purposes.
 // Note: This is currently hardcoded, but will likely be filled in by the build
 // system in future versions.
-enum VERSION = "0.11.0";
+enum VERSION = "1.0.0";
 
 /**
  * Functions used for logging inside Thrift.
diff --git a/lib/d/src/thrift/server/base.d b/lib/d/src/thrift/server/base.d
index f97adbe..a23b1c7 100644
--- a/lib/d/src/thrift/server/base.d
+++ b/lib/d/src/thrift/server/base.d
@@ -118,6 +118,38 @@
   TTransportFactory outputTransportFactory_;
   TProtocolFactory inputProtocolFactory_;
   TProtocolFactory outputProtocolFactory_;
+
+public:
+
+  @property TProcessorFactory processorFactory()
+  {
+    return processorFactory_;
+  }
+
+  @property TServerTransport serverTransport()
+  {
+    return serverTransport_;
+  }
+
+  @property TTransportFactory inputTransportFactory()
+  {
+    return inputTransportFactory_;
+  }
+
+  @property TTransportFactory outputTransportFactory()
+  {
+    return outputTransportFactory_;
+  }
+
+  @property TProtocolFactory inputProtocolFactory()
+  {
+    return inputProtocolFactory_;
+  }
+
+  @property TProtocolFactory outputProtocolFactory()
+  {
+    return outputProtocolFactory_;
+  }
 }
 
 /**
diff --git a/lib/d/src/thrift/server/nonblocking.d b/lib/d/src/thrift/server/nonblocking.d
index 0216799..5860c0c 100644
--- a/lib/d/src/thrift/server/nonblocking.d
+++ b/lib/d/src/thrift/server/nonblocking.d
@@ -893,14 +893,14 @@
       callsSinceResize_ = 0;
 
       factoryInputTransport_ =
-        server_.inputTransportFactory_.getTransport(inputTransport_);
+        server_.inputTransportFactory.getTransport(inputTransport_);
       factoryOutputTransport_ =
-        server_.outputTransportFactory_.getTransport(outputTransport_);
+        server_.outputTransportFactory.getTransport(outputTransport_);
 
       inputProtocol_ =
-        server_.inputProtocolFactory_.getProtocol(factoryInputTransport_);
+        server_.inputProtocolFactory.getProtocol(factoryInputTransport_);
       outputProtocol_ =
-        server_.outputProtocolFactory_.getProtocol(factoryOutputTransport_);
+        server_.outputProtocolFactory.getProtocol(factoryOutputTransport_);
 
       if (server_.eventHandler) {
         connectionContext_ =
@@ -908,7 +908,7 @@
       }
 
       auto info = TConnectionInfo(inputProtocol_, outputProtocol_, socket_);
-      processor_ = server_.processorFactory_.getProcessor(info);
+      processor_ = server_.processorFactory.getProcessor(info);
     }
 
     ~this() {
diff --git a/lib/d/src/thrift/server/simple.d b/lib/d/src/thrift/server/simple.d
index f7183a7..5aba4c1 100644
--- a/lib/d/src/thrift/server/simple.d
+++ b/lib/d/src/thrift/server/simple.d
@@ -140,7 +140,9 @@
           }
         }
       } catch (TTransportException ttx) {
-        logError("Client died: %s", ttx);
+        if (ttx.type() != TTransportException.Type.END_OF_FILE) {
+          logError("Client died unexpectedly: %s", ttx);
+        }
       } catch (Exception e) {
         logError("Uncaught exception: %s", e);
       }
diff --git a/lib/d/src/thrift/server/taskpool.d b/lib/d/src/thrift/server/taskpool.d
index b4720a4..670e720 100644
--- a/lib/d/src/thrift/server/taskpool.d
+++ b/lib/d/src/thrift/server/taskpool.d
@@ -268,7 +268,9 @@
         }
       }
     } catch (TTransportException ttx) {
-      logError("Client died: %s", ttx);
+      if (ttx.type() != TTransportException.Type.END_OF_FILE) {
+        logError("Client died unexpectedly: %s", ttx);
+      }
     } catch (Exception e) {
       logError("Uncaught exception: %s", e);
     }
diff --git a/lib/d/src/thrift/server/threaded.d b/lib/d/src/thrift/server/threaded.d
index 1cde983..300cc84 100644
--- a/lib/d/src/thrift/server/threaded.d
+++ b/lib/d/src/thrift/server/threaded.d
@@ -173,7 +173,9 @@
         }
       }
     } catch (TTransportException ttx) {
-      logError("Client died: %s", ttx);
+      if (ttx.type() != TTransportException.Type.END_OF_FILE) {
+        logError("Client died unexpectedly: %s", ttx);
+      }
     } catch (Exception e) {
       logError("Uncaught exception: %s", e);
     }
diff --git a/lib/d/src/thrift/server/transport/base.d b/lib/d/src/thrift/server/transport/base.d
index da165d3..704e16d 100644
--- a/lib/d/src/thrift/server/transport/base.d
+++ b/lib/d/src/thrift/server/transport/base.d
@@ -95,16 +95,7 @@
 
   ///
   this(Type type, string file = __FILE__, size_t line = __LINE__, Throwable next = null) {
-    string msg = "TTransportException: ";
-    switch (type) {
-      case Type.UNKNOWN: msg ~= "Unknown server transport exception"; break;
-      case Type.NOT_LISTENING: msg ~= "Server transport not listening"; break;
-      case Type.ALREADY_LISTENING: msg ~= "Server transport already listening"; break;
-      case Type.RESOURCE_FAILED: msg ~= "An underlying resource failed"; break;
-      default: msg ~= "(Invalid exception type)"; break;
-    }
-
-    this(msg, type, file, line, next);
+    this(errorMsg(type), type, file, line, next);
   }
 
   ///
@@ -129,5 +120,18 @@
 
 protected:
   Type type_;
+
+private:
+  string errorMsg(Type type) {
+    string msg = "TTransportException: ";
+    switch (type) {
+      case Type.UNKNOWN: msg ~= "Unknown server transport exception"; break;
+      case Type.NOT_LISTENING: msg ~= "Server transport not listening"; break;
+      case Type.ALREADY_LISTENING: msg ~= "Server transport already listening"; break;
+      case Type.RESOURCE_FAILED: msg ~= "An underlying resource failed"; break;
+      default: msg ~= "(Invalid exception type)"; break;
+    }
+    return msg;
+  }
 }
 
diff --git a/lib/d/src/thrift/transport/file.d b/lib/d/src/thrift/transport/file.d
index aac7289..fe88e73 100644
--- a/lib/d/src/thrift/transport/file.d
+++ b/lib/d/src/thrift/transport/file.d
@@ -37,7 +37,8 @@
 import std.algorithm : min, max;
 import std.concurrency;
 import std.conv : to;
-import std.datetime : AutoStart, dur, Duration, StopWatch;
+import std.datetime : dur, Duration;
+import std.datetime.stopwatch : AutoStart, StopWatch;
 import std.exception;
 import std.stdio : File;
 import thrift.base;
@@ -1076,15 +1077,15 @@
 
       // If any attempt takes more than 500ms, treat that as a fatal failure to
       // avoid looping over a potentially very slow operation.
-      enforce(sw.peek().msecs < 1500,
-        text("close() took ", sw.peek().msecs, "ms."));
+      enforce(sw.peek().total!"msecs" < 1500,
+        text("close() took ", sw.peek().total!"msecs", "ms."));
 
       // Normally, it takes less than 5ms on my dev box.
       // However, if the box is heavily loaded, some of the test runs can take
       // longer. Additionally, on a Windows Server 2008 instance running in
       // a VirtualBox VM, it has been observed that about a quarter of the runs
       // takes (217 ± 1) ms, for reasons not yet known.
-      if (sw.peek().msecs > 50) {
+      if (sw.peek().total!"msecs" > 50) {
         ++numOver;
       }
 
diff --git a/lib/d/src/thrift/transport/socket.d b/lib/d/src/thrift/transport/socket.d
index 228abf0..fcb38da 100644
--- a/lib/d/src/thrift/transport/socket.d
+++ b/lib/d/src/thrift/transport/socket.d
@@ -18,6 +18,7 @@
  */
 module thrift.transport.socket;
 
+import core.stdc.errno: ECONNRESET;
 import core.thread : Thread;
 import core.time : dur, Duration;
 import std.array : empty;
@@ -256,7 +257,7 @@
         new TCompoundOperationException(
           text(
             "All addresses tried failed (",
-            joiner(map!q{text(a._0, `: "`, a._1.msg, `"`)}(zip(addrs, errors)), ", "),
+            joiner(map!q{text(a[0], `: "`, a[1].msg, `"`)}(zip(addrs, errors)), ", "),
             ")."
           ),
           errors
diff --git a/lib/d/src/thrift/transport/ssl.d b/lib/d/src/thrift/transport/ssl.d
index fbcb6ee..f8ce40e 100644
--- a/lib/d/src/thrift/transport/ssl.d
+++ b/lib/d/src/thrift/transport/ssl.d
@@ -249,8 +249,12 @@
     }
     count_++;
 
-    ctx_ = SSL_CTX_new(SSLv23_method());
-    SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv2);
+    static if (OPENSSL_VERSION_NUMBER >= 0x1010000f) { // OPENSSL_VERSION_AT_LEAST(1, 1)) {
+        ctx_ = SSL_CTX_new(TLS_method());
+    } else {
+        ctx_ = SSL_CTX_new(SSLv23_method());
+        SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv2);
+    }
     SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3);   // THRIFT-3164
     enforce(ctx_, getSSLException("SSL_CTX_new"));
     SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY);
@@ -448,6 +452,7 @@
     }
     initialized_ = true;
 
+   static if (OPENSSL_VERSION_NUMBER < 0x1010000f) { // OPENSSL_VERSION_BEFORE(1, 1)) {
     SSL_library_init();
     SSL_load_error_strings();
 
@@ -465,12 +470,14 @@
     CRYPTO_set_dynlock_create_callback(assumeNothrow(&dynlockCreateCallback));
     CRYPTO_set_dynlock_lock_callback(assumeNothrow(&dynlockLockCallback));
     CRYPTO_set_dynlock_destroy_callback(assumeNothrow(&dynlockDestroyCallback));
+   }
   }
 
   static void cleanupOpenSSL() {
     if (!initialized_) return;
 
     initialized_ = false;
+   static if (OPENSSL_VERSION_NUMBER < 0x1010000f) { // OPENSSL_VERSION_BEFORE(1, 1)) {
     CRYPTO_set_locking_callback(null);
     CRYPTO_set_dynlock_create_callback(null);
     CRYPTO_set_dynlock_lock_callback(null);
@@ -478,6 +485,7 @@
     CRYPTO_cleanup_all_ex_data();
     ERR_free_strings();
     ERR_remove_state(0);
+   }
   }
 
   static extern(C) {
diff --git a/lib/d/test/client_pool_test.d b/lib/d/test/client_pool_test.d
index 85bcb29..b24c97a 100644
--- a/lib/d/test/client_pool_test.d
+++ b/lib/d/test/client_pool_test.d
@@ -18,6 +18,7 @@
  */
 module client_pool_test;
 
+import core.sync.semaphore : Semaphore;
 import core.time : Duration, dur;
 import core.thread : Thread;
 import std.algorithm;
@@ -28,6 +29,7 @@
 import std.range;
 import std.stdio;
 import std.typecons;
+import std.variant : Variant;
 import thrift.base;
 import thrift.async.libevent;
 import thrift.async.socket;
@@ -37,9 +39,12 @@
 import thrift.codegen.client;
 import thrift.codegen.client_pool;
 import thrift.codegen.processor;
+import thrift.protocol.base;
 import thrift.protocol.binary;
+import thrift.server.base;
 import thrift.server.simple;
 import thrift.server.transport.socket;
+import thrift.transport.base;
 import thrift.transport.buffered;
 import thrift.transport.socket;
 import thrift.util.cancellation;
@@ -108,11 +113,29 @@
   }
 }
 
+class ServerPreServeHandler : TServerEventHandler {
+  this(Semaphore sem) {
+    sem_ = sem;
+  }
+
+  override void preServe() {
+    sem_.notify();
+  }
+
+  Variant createContext(TProtocol input, TProtocol output) { return Variant.init; }
+  void deleteContext(Variant serverContext, TProtocol input, TProtocol output) {}
+  void preProcess(Variant serverContext, TTransport transport) {}
+
+private:
+  Semaphore sem_;
+}
+
 class ServerThread : Thread {
-  this(ExTestHandler handler, TCancellation cancellation) {
+  this(ExTestHandler handler, ServerPreServeHandler serverHandler, TCancellation cancellation) {
     super(&run);
     handler_ = handler;
     cancellation_ = cancellation;
+    serverHandler_ = serverHandler;
   }
 private:
   void run() {
@@ -123,16 +146,17 @@
       serverTransport.recvTimeout = dur!"seconds"(3);
       auto transportFactory = new TBufferedTransportFactory;
 
-      auto server = new TSimpleServer(
-        processor, serverTransport, transportFactory, protocolFactory);
+      auto server = new TSimpleServer(processor, serverTransport, transportFactory, protocolFactory);
+      server.eventHandler = serverHandler_;
       server.serve(cancellation_);
     } catch (Exception e) {
       writefln("Server thread on port %s failed: %s", handler_.port, e);
     }
   }
 
-  TCancellation cancellation_;
   ExTestHandler handler_;
+  ServerPreServeHandler serverHandler_;
+  TCancellation cancellation_;
 }
 
 void main(string[] args) {
@@ -145,6 +169,9 @@
 
   immutable ports = cast(immutable)array(map!"cast(ushort)a"(iota(port, port + 6)));
 
+  // semaphore that will be incremented whenever each server thread has bound and started listening
+  Semaphore sem = new Semaphore(0);
+
 version (none) {
   // Cannot use this due to multiple DMD @@BUG@@s:
   // 1. »function D main is a nested function and cannot be accessed from array«
@@ -174,11 +201,10 @@
 }
 
   // Fire up the server threads.
-  foreach (h; handlers) (new ServerThread(h, serverCancellation)).start();
+  foreach (h; handlers) (new ServerThread(h, new ServerPreServeHandler(sem), serverCancellation)).start();
 
-  // Give the servers some time to get up. This should really be accomplished
-  // via a barrier here and in the preServe() hook.
-  Thread.sleep(dur!"msecs"(10));
+  // wait until all the handlers signal that they're ready to serve
+  foreach (h; handlers) (sem.wait(dur!`seconds`(1)));
 
   syncClientPoolTest(ports, handlers);
   asyncClientPoolTest(ports, handlers);
@@ -409,8 +435,8 @@
     )();
     Thread.sleep(dur!"msecs"(20));
     auto resultTuple = partialResult.finishGet();
-    enforce(resultTuple._0 == ports[0 .. 2]);
-    enforce(equal(map!"a.port"(cast(TestServiceException[])resultTuple._1),
+    enforce(resultTuple[0] == ports[0 .. 2]);
+    enforce(equal(map!"a.port"(cast(TestServiceException[])resultTuple[1]),
       ports[3 .. $ - 1]));
   }
 }
diff --git a/lib/d/test/serialization_benchmark.d b/lib/d/test/serialization_benchmark.d
index 35515c8..40d0480 100644
--- a/lib/d/test/serialization_benchmark.d
+++ b/lib/d/test/serialization_benchmark.d
@@ -13,7 +13,7 @@
  */
 module serialization_benchmark;
 
-import std.datetime : AutoStart, StopWatch;
+import std.datetime.stopwatch : AutoStart, StopWatch;
 import std.math : PI;
 import std.stdio;
 import thrift.protocol.binary;
@@ -46,7 +46,7 @@
     }
     sw.stop();
 
-    auto msecs = sw.peek().msecs;
+    auto msecs = sw.peek().total!"msecs";
     writefln("Write: %s ms (%s kHz)", msecs, ITERATIONS / msecs);
   }
 
@@ -64,7 +64,7 @@
     }
     sw.stop();
 
-    auto msecs = sw.peek().msecs;
+    auto msecs = sw.peek().total!"msecs";
     writefln(" Read: %s ms (%s kHz)", msecs, ITERATIONS / msecs);
   }
 }
diff --git a/lib/d/test/thrift_test_server.d b/lib/d/test/thrift_test_server.d
index 71ab917..b582253 100644
--- a/lib/d/test/thrift_test_server.d
+++ b/lib/d/test/thrift_test_server.d
@@ -16,8 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 module thrift_test_server;
 
+import core.stdc.errno : errno;
+import core.stdc.signal : signal, sigfn_t, SIGINT, SIG_DFL, SIG_ERR;
 import core.thread : dur, Thread;
 import std.algorithm;
 import std.exception : enforce;
@@ -40,6 +43,7 @@
 import thrift.transport.framed;
 import thrift.transport.http;
 import thrift.transport.ssl;
+import thrift.util.cancellation;
 import thrift.util.hashset;
 import test_utils;
 
@@ -205,14 +209,44 @@
   bool trace_;
 }
 
+shared(bool) gShutdown = false;
+
+nothrow @nogc extern(C) void handleSignal(int sig) {
+  gShutdown = true;
+}
+
+// Runs a thread that waits for shutdown to be
+// signaled and then triggers cancellation,
+// causing the server to stop.  While we could
+// use a signalfd for this purpose, we are instead
+// opting for a busy waiting scheme for maximum
+// portability since signalfd is a linux thing.
+
+class ShutdownThread : Thread {
+  this(TCancellationOrigin cancellation) {
+    cancellation_ = cancellation;
+    super(&run);
+  }
+  
+private:
+  void run() {
+    while (!gShutdown) {
+      Thread.sleep(dur!("msecs")(25));
+    }
+    cancellation_.trigger();
+  }
+  
+  TCancellationOrigin cancellation_;
+}
+
 void main(string[] args) {
   ushort port = 9090;
   ServerType serverType;
   ProtocolType protocolType;
   size_t numIOThreads = 1;
   TransportType transportType;
-  bool ssl;
-  bool trace;
+  bool ssl = false;
+  bool trace = true;
   size_t taskPoolSize = totalCPUs;
 
   getopt(args, "port", &port, "protocol", &protocolType, "server-type",
@@ -279,8 +313,26 @@
   auto server = createServer(serverType, numIOThreads, taskPoolSize,
     processor, serverSocket, transportFactory, protocolFactory);
 
+  // Set up SIGINT signal handling
+  sigfn_t oldHandler = signal(SIGINT, &handleSignal);
+  enforce(oldHandler != SIG_ERR,
+    "Could not replace the SIGINT signal handler: errno {0}".format(errno()));
+  
+  // Set up a server cancellation trigger
+  auto cancel = new TCancellationOrigin();
+
+  // Set up a listener for the shutdown condition - this will
+  // wake up when the signal occurs and trigger cancellation.
+  auto shutdown = new ShutdownThread(cancel);
+  shutdown.start();
+  
+  // Serve from this thread; the signal will stop the server
+  // and control will return here
   writefln("Starting %s/%s %s ThriftTest server %son port %s...", protocolType,
     transportType, serverType, ssl ? "(using SSL) ": "", port);
-  server.serve();
+  server.serve(cancel);
+  shutdown.join();
+  signal(SIGINT, SIG_DFL);
+    
   writeln("done.");
 }
diff --git a/lib/dart/LICENSE_HEADER b/lib/dart/LICENSE
similarity index 100%
rename from lib/dart/LICENSE_HEADER
rename to lib/dart/LICENSE
diff --git a/lib/dart/lib/src/transport/t_framed_transport.dart b/lib/dart/lib/src/transport/t_framed_transport.dart
index 80ccf2c..2ef03f7 100644
--- a/lib/dart/lib/src/transport/t_framed_transport.dart
+++ b/lib/dart/lib/src/transport/t_framed_transport.dart
@@ -25,7 +25,14 @@
 
   final TTransport _transport;
 
-  final Uint8List headerBytes = new Uint8List(headerByteCount);
+  final Uint8List _headerBytes = new Uint8List(headerByteCount);
+  int _receivedHeaderBytes = 0;
+
+  int _bodySize = 0;
+  Uint8List _body = null;
+  int _receivedBodyBytes = 0;
+
+  Completer<Uint8List> _frameCompleter = null;
 
   TFramedTransport(TTransport transport) : _transport = transport {
     if (transport == null) {
@@ -51,33 +58,112 @@
       if (got > 0) return got;
     }
 
-    _readFrame();
+    // IMPORTANT: by the time you've got here,
+    // an entire frame is available for reading
 
     return super.read(buffer, offset, length);
   }
 
   void _readFrame() {
-    _transport.readAll(headerBytes, 0, headerByteCount);
-    int size = headerBytes.buffer.asByteData().getUint32(0);
-
-    if (size < 0) {
-      throw new TTransportError(
-          TTransportErrorType.UNKNOWN, "Read a negative frame size: $size");
+    if (_body == null) {
+      bool gotFullHeader = _readFrameHeader();
+      if (!gotFullHeader) {
+        return;
+      }
     }
 
-    Uint8List buffer = new Uint8List(size);
-    _transport.readAll(buffer, 0, size);
-    _setReadBuffer(buffer);
+    _readFrameBody();
+  }
+
+  bool _readFrameHeader() {
+    var remainingHeaderBytes = headerByteCount - _receivedHeaderBytes;
+
+    int got = _transport.read(_headerBytes, _receivedHeaderBytes, remainingHeaderBytes);
+    if (got < 0) {
+      throw new TTransportError(
+          TTransportErrorType.UNKNOWN, "Socket closed during frame header read");
+    }
+
+    _receivedHeaderBytes += got;
+
+    if (_receivedHeaderBytes == headerByteCount) {
+      int size = _headerBytes.buffer.asByteData().getUint32(0);
+
+      _receivedHeaderBytes = 0;
+
+      if (size < 0) {
+        throw new TTransportError(
+            TTransportErrorType.UNKNOWN, "Read a negative frame size: $size");
+      }
+
+      _bodySize = size;
+      _body = new Uint8List(_bodySize);
+      _receivedBodyBytes = 0;
+
+      return true;
+    } else {
+      _registerForReadableBytes();
+      return false;
+    }
+  }
+
+  void _readFrameBody() {
+    var remainingBodyBytes = _bodySize - _receivedBodyBytes;
+
+    int got = _transport.read(_body, _receivedBodyBytes, remainingBodyBytes);
+    if (got < 0) {
+      throw new TTransportError(
+          TTransportErrorType.UNKNOWN, "Socket closed during frame body read");
+    }
+
+    _receivedBodyBytes += got;
+
+    if (_receivedBodyBytes == _bodySize) {
+      var body = _body;
+
+      _bodySize = 0;
+      _body = null;
+      _receivedBodyBytes = 0;
+
+      _setReadBuffer(body);
+
+      var completer = _frameCompleter;
+      _frameCompleter = null;
+      completer.complete(new Uint8List(0));
+    } else {
+      _registerForReadableBytes();
+    }
   }
 
   Future flush() {
-    Uint8List buffer = consumeWriteBuffer();
-    int length = buffer.length;
+    if (_frameCompleter == null) {
+      Uint8List buffer = consumeWriteBuffer();
+      int length = buffer.length;
 
-    headerBytes.buffer.asByteData().setUint32(0, length);
-    _transport.write(headerBytes, 0, headerByteCount);
-    _transport.write(buffer, 0, length);
+      _headerBytes.buffer.asByteData().setUint32(0, length);
+      _transport.write(_headerBytes, 0, headerByteCount);
+      _transport.write(buffer, 0, length);
 
-    return _transport.flush();
+      _frameCompleter  = new Completer<Uint8List>();
+      _registerForReadableBytes();
+    }
+
+    return _frameCompleter.future;
+  }
+
+  void _registerForReadableBytes() {
+    _transport.flush().then((_) {
+      _readFrame();
+    }).catchError((e) {
+      var completer = _frameCompleter;
+
+      _receivedHeaderBytes = 0;
+      _bodySize = 0;
+      _body = null;
+      _receivedBodyBytes = 0;
+      _frameCompleter = null;
+
+      completer.completeError(e);
+    });
   }
 }
diff --git a/lib/dart/lib/src/transport/t_socket_transport.dart b/lib/dart/lib/src/transport/t_socket_transport.dart
index 8dcdfde..c41374a 100644
--- a/lib/dart/lib/src/transport/t_socket_transport.dart
+++ b/lib/dart/lib/src/transport/t_socket_transport.dart
@@ -79,7 +79,9 @@
     var completer = new Completer<Uint8List>.sync();
     _completers.add(completer);
 
-    socket.send(bytes);
+    if (bytes.lengthInBytes > 0) {
+      socket.send(bytes);
+    }
 
     return completer.future;
   }
diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml
index 5d04226..fdc4a0d 100644
--- a/lib/dart/pubspec.yaml
+++ b/lib/dart/pubspec.yaml
@@ -16,7 +16,7 @@
 # under the License.
 
 name: thrift
-version: 0.11.0
+version: 1.0.0
 description: >
   A Dart library for Apache Thrift
 author: Apache Thrift Developers <dev@thrift.apache.org>
@@ -33,7 +33,7 @@
 
 dev_dependencies:
   # test
-  mockito: ^0.11.0
+  mockito: ^1.0.0
   test: ^0.12.0
 
   # dart_dev - https://github.com/Workiva/dart_dev
diff --git a/lib/dart/test/transport/t_framed_transport_test.dart b/lib/dart/test/transport/t_framed_transport_test.dart
new file mode 100644
index 0000000..e072e68
--- /dev/null
+++ b/lib/dart/test/transport/t_framed_transport_test.dart
@@ -0,0 +1,175 @@
+// 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.
+
+library thrift.test.transport.t_framed_transport_test;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:typed_data' show Uint8List;
+
+import 'package:test/test.dart';
+import 'package:thrift/thrift.dart';
+
+void main() {
+  group('TFramedTransport partial reads', () {
+    final flushAwaitDuration = new Duration(seconds: 10);
+
+    FakeReadOnlySocket socket;
+    TSocketTransport socketTransport;
+    TFramedTransport transport;
+    var messageAvailable;
+
+    setUp(() {
+      socket = new FakeReadOnlySocket();
+      socketTransport = new TClientSocketTransport(socket);
+      transport = new TFramedTransport(socketTransport);
+      messageAvailable = false;
+    });
+
+    expectNoReadableBytes() {
+      var readBuffer = new Uint8List(128);
+      var readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes);
+      expect(readBytes, 0);
+      expect(messageAvailable, false);
+    }
+
+    test('Test transport reads messages where header and body are sent separately', () async {
+      // buffer into which we'll read
+      var readBuffer = new Uint8List(10);
+      var readBytes;
+
+      // registers for readable bytes
+      var flushFuture = transport.flush().timeout(flushAwaitDuration);
+      flushFuture.then((_) {
+        messageAvailable = true;
+      });
+
+      // write header bytes
+      socket.messageController.add(new Uint8List.fromList([0x00, 0x00, 0x00, 0x06]));
+
+      // you shouldn't be able to get any bytes from the read,
+      // because the header has been consumed internally
+      expectNoReadableBytes();
+
+      // write first batch of body
+      socket.messageController.add(new Uint8List.fromList(UTF8.encode("He")));
+
+      // you shouldn't be able to get any bytes from the read,
+      // because the frame has been consumed internally
+      expectNoReadableBytes();
+
+      // write second batch of body
+      socket.messageController.add(new Uint8List.fromList(UTF8.encode("llo!")));
+
+      // have to wait for the flush to complete,
+      // because it's only then that the frame is available for reading
+      await flushFuture;
+      expect(messageAvailable, true);
+
+      // at this point the frame is complete, so we expect the read to complete
+      readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes);
+      expect(readBytes, 6);
+      expect(readBuffer.sublist(0, 6), UTF8.encode("Hello!"));
+    });
+
+    test('Test transport reads messages where header is sent in pieces '
+         'and body is also sent in pieces', () async {
+      // buffer into which we'll read
+      var readBuffer = new Uint8List(10);
+      var readBytes;
+
+      // registers for readable bytes
+      var flushFuture = transport.flush().timeout(flushAwaitDuration);
+      flushFuture.then((_) {
+        messageAvailable = true;
+      });
+
+      // write first part of header bytes
+      socket.messageController.add(new Uint8List.fromList([0x00, 0x00]));
+
+      // you shouldn't be able to get any bytes from the read
+      expectNoReadableBytes();
+
+      // write second part of header bytes
+      socket.messageController.add(new Uint8List.fromList([0x00, 0x03]));
+
+      // you shouldn't be able to get any bytes from the read again
+      // because only the header was read, and there's no frame body
+      readBytes = expectNoReadableBytes();
+
+      // write first batch of body
+      socket.messageController.add(new Uint8List.fromList(UTF8.encode("H")));
+
+      // you shouldn't be able to get any bytes from the read,
+      // because the frame has been consumed internally
+      expectNoReadableBytes();
+
+      // write second batch of body
+      socket.messageController.add(new Uint8List.fromList(UTF8.encode("i!")));
+
+      // have to wait for the flush to complete,
+      // because it's only then that the frame is available for reading
+      await flushFuture;
+      expect(messageAvailable, true);
+
+      // at this point the frame is complete, so we expect the read to complete
+      readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes);
+      expect(readBytes, 3);
+      expect(readBuffer.sublist(0, 3), UTF8.encode("Hi!"));
+    });
+  });
+}
+
+
+
+class FakeReadOnlySocket extends TSocket {
+
+  StreamController<Uint8List> messageController = new StreamController<Uint8List>(sync: true);
+  StreamController<Object> errorController = new StreamController<Object>();
+  StreamController<TSocketState> stateController = new StreamController<TSocketState>();
+
+  @override
+  Future close() {
+    // noop
+  }
+
+  @override
+  bool get isClosed => false;
+
+  @override
+  bool get isOpen => true;
+
+  @override
+  Stream<Object> get onError => errorController.stream;
+
+  @override
+  Stream<Uint8List> get onMessage => messageController.stream;
+
+  @override
+  Stream<TSocketState> get onState => stateController.stream;
+
+  @override
+  Future open() {
+    // noop
+  }
+
+  @override
+  void send(Uint8List data) {
+    // noop
+  }
+}
+
diff --git a/lib/delphi/DelphiThrift.groupproj b/lib/delphi/DelphiThrift.groupproj
new file mode 100644
index 0000000..a172e49
--- /dev/null
+++ b/lib/delphi/DelphiThrift.groupproj
@@ -0,0 +1,156 @@
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+		<PropertyGroup>
+			<ProjectGuid>{6BD327A5-7688-4263-B6A8-B15207CF4EC5}</ProjectGuid>
+		</PropertyGroup>
+		<ItemGroup>
+			<Projects Include="test\client.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\server.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\multiplexed\Multiplex.Test.Client.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\multiplexed\Multiplex.Test.Server.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\serializer\TestSerializer.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\skip\skiptest_version1.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\skip\skiptest_version2.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\typeregistry\TestTypeRegistry.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="..\..\tutorial\delphi\DelphiServer\DelphiServer.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="..\..\tutorial\delphi\DelphiClient\DelphiClient.dproj">
+				<Dependencies/>
+			</Projects>
+			<Projects Include="test\keywords\ReservedKeywords.dproj">
+				<Dependencies/>
+			</Projects>
+		</ItemGroup>
+		<ProjectExtensions>
+			<Borland.Personality>Default.Personality.12</Borland.Personality>
+			<Borland.ProjectType/>
+			<BorlandProject>
+				<Default.Personality/>
+			</BorlandProject>
+		</ProjectExtensions>
+		<Target Name="client">
+			<MSBuild Projects="test\client.dproj"/>
+		</Target>
+		<Target Name="client:Clean">
+			<MSBuild Projects="test\client.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="client:Make">
+			<MSBuild Projects="test\client.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="server">
+			<MSBuild Projects="test\server.dproj"/>
+		</Target>
+		<Target Name="server:Clean">
+			<MSBuild Projects="test\server.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="server:Make">
+			<MSBuild Projects="test\server.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="Multiplex_Test_Client">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Client.dproj"/>
+		</Target>
+		<Target Name="Multiplex_Test_Client:Clean">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Client.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="Multiplex_Test_Client:Make">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Client.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="Multiplex_Test_Server">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Server.dproj"/>
+		</Target>
+		<Target Name="Multiplex_Test_Server:Clean">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Server.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="Multiplex_Test_Server:Make">
+			<MSBuild Projects="test\multiplexed\Multiplex.Test.Server.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="TestSerializer">
+			<MSBuild Projects="test\serializer\TestSerializer.dproj"/>
+		</Target>
+		<Target Name="TestSerializer:Clean">
+			<MSBuild Projects="test\serializer\TestSerializer.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="TestSerializer:Make">
+			<MSBuild Projects="test\serializer\TestSerializer.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="skiptest_version1">
+			<MSBuild Projects="test\skip\skiptest_version1.dproj"/>
+		</Target>
+		<Target Name="skiptest_version1:Clean">
+			<MSBuild Projects="test\skip\skiptest_version1.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="skiptest_version1:Make">
+			<MSBuild Projects="test\skip\skiptest_version1.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="skiptest_version2">
+			<MSBuild Projects="test\skip\skiptest_version2.dproj"/>
+		</Target>
+		<Target Name="skiptest_version2:Clean">
+			<MSBuild Projects="test\skip\skiptest_version2.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="skiptest_version2:Make">
+			<MSBuild Projects="test\skip\skiptest_version2.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="TestTypeRegistry">
+			<MSBuild Projects="test\typeregistry\TestTypeRegistry.dproj"/>
+		</Target>
+		<Target Name="TestTypeRegistry:Clean">
+			<MSBuild Projects="test\typeregistry\TestTypeRegistry.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="TestTypeRegistry:Make">
+			<MSBuild Projects="test\typeregistry\TestTypeRegistry.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="DelphiServer">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiServer\DelphiServer.dproj"/>
+		</Target>
+		<Target Name="DelphiServer:Clean">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiServer\DelphiServer.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="DelphiServer:Make">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiServer\DelphiServer.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="DelphiClient">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiClient\DelphiClient.dproj"/>
+		</Target>
+		<Target Name="DelphiClient:Clean">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiClient\DelphiClient.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="DelphiClient:Make">
+			<MSBuild Projects="..\..\tutorial\delphi\DelphiClient\DelphiClient.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="ReservedKeywords">
+			<MSBuild Projects="test\keywords\ReservedKeywords.dproj"/>
+		</Target>
+		<Target Name="ReservedKeywords:Clean">
+			<MSBuild Projects="test\keywords\ReservedKeywords.dproj" Targets="Clean"/>
+		</Target>
+		<Target Name="ReservedKeywords:Make">
+			<MSBuild Projects="test\keywords\ReservedKeywords.dproj" Targets="Make"/>
+		</Target>
+		<Target Name="Build">
+			<CallTarget Targets="client;server;Multiplex_Test_Client;Multiplex_Test_Server;TestSerializer;skiptest_version1;skiptest_version2;TestTypeRegistry;DelphiServer;DelphiClient;ReservedKeywords"/>
+		</Target>
+		<Target Name="Clean">
+			<CallTarget Targets="client:Clean;server:Clean;Multiplex_Test_Client:Clean;Multiplex_Test_Server:Clean;TestSerializer:Clean;skiptest_version1:Clean;skiptest_version2:Clean;TestTypeRegistry:Clean;DelphiServer:Clean;DelphiClient:Clean;ReservedKeywords:Clean"/>
+		</Target>
+		<Target Name="Make">
+			<CallTarget Targets="client:Make;server:Make;Multiplex_Test_Client:Make;Multiplex_Test_Server:Make;TestSerializer:Make;skiptest_version1:Make;skiptest_version2:Make;TestTypeRegistry:Make;DelphiServer:Make;DelphiClient:Make;ReservedKeywords:Make"/>
+		</Target>
+		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Group.Targets')" Project="$(BDS)\Bin\CodeGear.Group.Targets"/>
+	</Project>
diff --git a/lib/delphi/src/Thrift.Exception.pas b/lib/delphi/src/Thrift.Exception.pas
new file mode 100644
index 0000000..5d15c36
--- /dev/null
+++ b/lib/delphi/src/Thrift.Exception.pas
@@ -0,0 +1,62 @@
+(*
+ * 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.
+ *)
+
+{$SCOPEDENUMS ON}
+
+unit Thrift.Exception;
+
+interface
+
+uses
+  Classes, SysUtils;
+
+type
+  // base class for all Thrift exceptions
+  TException = class( SysUtils.Exception)
+  public
+    function Message : string;        // hide inherited property: allow read, but prevent accidental writes
+    procedure UpdateMessageProperty;  // update inherited message property with toString()
+  end;
+
+
+
+
+implementation
+
+{ TException }
+
+function TException.Message;
+// allow read (exception summary), but prevent accidental writes
+// read will return the exception summary
+begin
+  result := Self.ToString;
+end;
+
+procedure TException.UpdateMessageProperty;
+// Update the inherited Message property to better conform to standard behaviour.
+// Nice benefit: The IDE is now able to show the exception message again.
+begin
+  inherited Message := Self.ToString;  // produces a summary text
+end;
+
+
+
+
+end.
+
diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas
index 4cd80ba..8cf23db 100644
--- a/lib/delphi/src/Thrift.Processor.Multiplex.pas
+++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas
@@ -53,11 +53,11 @@
 
 type
   IMultiplexedProcessor = interface( IProcessor)
-    ['{810FF32D-22A2-4D58-B129-B0590703ECEC}']
+    ['{807F9D19-6CF4-4789-840E-93E87A12EB63}']
     // Register a service with this TMultiplexedProcessor.  This allows us
     // to broker requests to individual services by using the service name
     // to select them at request time.
-    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor);
+    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE);
   end;
 
 
@@ -76,6 +76,7 @@
 
   private
     FServiceProcessorMap : TDictionary<String, IProcessor>;
+    FDefaultProcessor : IProcessor;
 
     procedure Error( const oprot : IProtocol; const msg : TThriftMessage;
                      extype : TApplicationExceptionSpecializedClass; const etxt : string);
@@ -87,7 +88,7 @@
     // Register a service with this TMultiplexedProcessorImpl.  This allows us
     // to broker requests to individual services by using the service name
     // to select them at request time.
-    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor);
+    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE);
 
     { This implementation of process performs the following steps:
       - Read the beginning of the message.
@@ -135,9 +136,15 @@
 end;
 
 
-procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor);
+procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean);
 begin
   FServiceProcessorMap.Add( serviceName, processor);
+
+  if asDefault then begin
+    if FDefaultProcessor = nil
+    then FDefaultProcessor := processor
+    else raise TApplicationExceptionInternalError.Create('Only one default service allowed');
+  end;
 end;
 
 
@@ -184,28 +191,37 @@
   end;
 
   // Extract the service name
+  // use FDefaultProcessor as fallback if there is no separator
   idx := Pos( TMultiplexedProtocol.SEPARATOR, msg.Name);
-  if idx < 1 then begin
+  if idx > 0 then begin
+
+    // Create a new TMessage, something that can be consumed by any TProtocol
+    sService := Copy( msg.Name, 1, idx-1);
+    if not FServiceProcessorMap.TryGetValue( sService, processor)
+    then begin
+      Error( oprot, msg,
+             TApplicationExceptionInternalError,
+             Format(ERROR_UNKNOWN_SERVICE,[sService]));
+      Exit( FALSE);
+    end;
+
+    // Create a new TMessage, removing the service name
+    Inc( idx, Length(TMultiplexedProtocol.SEPARATOR));
+    Init( newMsg, Copy( msg.Name, idx, MAXINT), msg.Type_, msg.SeqID);
+
+  end
+  else if FDefaultProcessor <> nil then begin
+    processor := FDefaultProcessor;
+    newMsg    := msg;  // no need to change
+
+  end
+  else begin
     Error( oprot, msg,
            TApplicationExceptionInvalidProtocol,
            Format(ERROR_INCOMPATIBLE_PROT,[msg.Name]));
     Exit( FALSE);
   end;
 
-  // Create a new TMessage, something that can be consumed by any TProtocol
-  sService := Copy( msg.Name, 1, idx-1);
-  if not FServiceProcessorMap.TryGetValue( sService, processor)
-  then begin
-    Error( oprot, msg,
-           TApplicationExceptionInternalError,
-           Format(ERROR_UNKNOWN_SERVICE,[sService]));
-    Exit( FALSE);
-  end;
-
-  // Create a new TMessage, removing the service name
-  Inc( idx, Length(TMultiplexedProtocol.SEPARATOR));
-  Init( newMsg, Copy( msg.Name, idx, MAXINT), msg.Type_, msg.SeqID);
-
   // Dispatch processing to the stored processor
   protocol := TStoredMessageProtocol.Create( iprot, newMsg);
   result   := processor.process( protocol, oprot, events);
@@ -213,4 +229,3 @@
 
 
 end.
-
diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas
index 5b1253a..1c1b3da 100644
--- a/lib/delphi/src/Thrift.Protocol.Compact.pas
+++ b/lib/delphi/src/Thrift.Protocol.Compact.pas
@@ -1088,11 +1088,29 @@
 {$ENDIF}
 
 
+{$IFDEF Debug}
+procedure UnitTest;
+var w : WORD;
+const FPU_CW_DENORMALIZED = $0002;
+begin
+  w := Get8087CW;
+  try
+    Set8087CW( w or FPU_CW_DENORMALIZED);
+
+    TestDoubleToInt64Bits;
+    TestZigZag;
+    TestLongBytes;
+
+  finally
+    Set8087CW( w);
+  end;
+end;
+{$ENDIF}
+
+
 initialization
   {$IFDEF Debug}
-  TestDoubleToInt64Bits;
-  TestZigZag;
-  TestLongBytes;
+  UnitTest;
   {$ENDIF}
 
 end.
diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas
index 24f6791..36509ca 100644
--- a/lib/delphi/src/Thrift.Protocol.pas
+++ b/lib/delphi/src/Thrift.Protocol.pas
@@ -27,6 +27,7 @@
   Classes,
   SysUtils,
   Contnrs,
+  Thrift.Exception,
   Thrift.Stream,
   Thrift.Collections,
   Thrift.Transport;
@@ -116,7 +117,7 @@
     function Append(const Value: IThriftContainer): TStringBuilder; overload;
   end;
 
-  TProtocolException = class( Exception )
+  TProtocolException = class( TException)
   public
     const // TODO(jensg): change into enum
       UNKNOWN = 0;
diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas
index b6e0cbf..3308c53 100644
--- a/lib/delphi/src/Thrift.Stream.pas
+++ b/lib/delphi/src/Thrift.Stream.pas
@@ -132,6 +132,7 @@
 end;
 
 function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
+var pTmp : PByte;
 begin
   inherited;
 
@@ -141,7 +142,9 @@
   Result := 0;
   if FStream <> nil then begin
     if count > 0 then begin
-      FStream.Read( @(PByteArray(pBuf)^[offset]), count, @Result);
+      pTmp := pBuf;
+      Inc( pTmp, offset);
+      FStream.Read( pTmp, count, @Result);
     end;
   end;
 end;
@@ -172,11 +175,14 @@
 
 procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer);
 var nWritten : Integer;
+    pTmp : PByte;
 begin
   inherited;
   if IsOpen then begin
     if count > 0 then begin
-      FStream.Write( @(PByteArray(pBuf)^[offset]), count, @nWritten);
+      pTmp := pBuf;
+      Inc( pTmp, offset);
+      FStream.Write( pTmp, count, @nWritten);
     end;
   end;
 end;
@@ -259,14 +265,18 @@
 end;
 
 function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
+var pTmp : PByte;
 begin
   inherited;
 
   if count >= buflen-offset
   then count := buflen-offset;
 
-  if count > 0
-  then Result := FStream.Read( PByteArray(pBuf)^[offset], count)
+  if count > 0 then begin
+    pTmp := pBuf;
+    Inc( pTmp, offset);
+    Result := FStream.Read( pTmp^, count)
+  end
   else Result := 0;
 end;
 
@@ -296,10 +306,13 @@
 end;
 
 procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer);
+var pTmp : PByte;
 begin
   inherited;
   if count > 0 then begin
-    FStream.Write( PByteArray(pBuf)^[offset], count)
+    pTmp := pBuf;
+    Inc( pTmp, offset);
+    FStream.Write( pTmp^, count)
   end;
 end;
 
diff --git a/lib/delphi/src/Thrift.Transport.Pipes.pas b/lib/delphi/src/Thrift.Transport.Pipes.pas
index aace4bb..77a343b 100644
--- a/lib/delphi/src/Thrift.Transport.Pipes.pas
+++ b/lib/delphi/src/Thrift.Transport.Pipes.pas
@@ -328,6 +328,7 @@
 
 procedure TPipeStreamBase.WriteDirect( const pBuf : Pointer; offset: Integer; count: Integer);
 var cbWritten, nBytes : DWORD;
+    pData : PByte;
 begin
   if not IsOpen
   then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe');
@@ -336,11 +337,13 @@
   // there's a system limit around 0x10000 bytes that we hit otherwise
   // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section."
   nBytes := Min( 15*4096, count); // 16 would exceed the limit
+  pData  := pBuf;
+  Inc( pData, offset);
   while nBytes > 0 do begin
-    if not WriteFile( FPipe, PByteArray(pBuf)^[offset], nBytes, cbWritten, nil)
+    if not WriteFile( FPipe, pData^, nBytes, cbWritten, nil)
     then raise TTransportExceptionNotOpen.Create('Write to pipe failed');
 
-    Inc( offset, cbWritten);
+    Inc( pData, cbWritten);
     Dec( count, cbWritten);
     nBytes := Min( nBytes, count);
   end;
@@ -350,6 +353,7 @@
 procedure TPipeStreamBase.WriteOverlapped( const pBuf : Pointer; offset: Integer; count: Integer);
 var cbWritten, dwWait, dwError, nBytes : DWORD;
     overlapped : IOverlappedHelper;
+    pData : PByte;
 begin
   if not IsOpen
   then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe');
@@ -358,17 +362,21 @@
   // there's a system limit around 0x10000 bytes that we hit otherwise
   // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section."
   nBytes := Min( 15*4096, count); // 16 would exceed the limit
+  pData  := pBuf;
+  Inc( pData, offset);
   while nBytes > 0 do begin
     overlapped := TOverlappedHelperImpl.Create;
-    if not WriteFile( FPipe, PByteArray(pBuf)^[offset], nBytes, cbWritten, overlapped.OverlappedPtr)
+    if not WriteFile( FPipe, pData^, nBytes, cbWritten, overlapped.OverlappedPtr)
     then begin
       dwError := GetLastError;
       case dwError of
         ERROR_IO_PENDING : begin
           dwWait := overlapped.WaitFor(FTimeout);
 
-          if (dwWait = WAIT_TIMEOUT)
-          then raise TTransportExceptionTimedOut.Create('Pipe write timed out');
+          if (dwWait = WAIT_TIMEOUT) then begin
+            CancelIo( FPipe);  // prevents possible AV on invalid overlapped ptr
+            raise TTransportExceptionTimedOut.Create('Pipe write timed out');
+          end;
 
           if (dwWait <> WAIT_OBJECT_0)
           or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbWritten, TRUE)
@@ -382,7 +390,7 @@
 
     ASSERT( DWORD(nBytes) = cbWritten);
 
-    Inc( offset, cbWritten);
+    Inc( pData, cbWritten);
     Dec( count, cbWritten);
     nBytes := Min( nBytes, count);
   end;
@@ -393,6 +401,7 @@
 var cbRead, dwErr, nRemaining  : DWORD;
     bytes, retries  : LongInt;
     bOk     : Boolean;
+    pData   : PByte;
 const INTERVAL = 10;  // ms
 begin
   if not IsOpen
@@ -427,14 +436,16 @@
 
   result := 0;
   nRemaining := count;
+  pData := pBuf;
+  Inc( pData, offset);
   while nRemaining > 0 do begin
     // read the data (or block INFINITE-ly)
-    bOk := ReadFile( FPipe, PByteArray(pBuf)^[offset], nRemaining, cbRead, nil);
+    bOk := ReadFile( FPipe, pData^, nRemaining, cbRead, nil);
     if (not bOk) and (GetLastError() <> ERROR_MORE_DATA)
     then Break; // No more data, possibly because client disconnected.
 
     Dec( nRemaining, cbRead);
-    Inc( offset, cbRead);
+    Inc( pData, cbRead);
     Inc( result, cbRead);
   end;
 end;
@@ -444,25 +455,30 @@
 var cbRead, dwWait, dwError, nRemaining : DWORD;
     bOk     : Boolean;
     overlapped : IOverlappedHelper;
+    pData   : PByte;
 begin
   if not IsOpen
   then raise TTransportExceptionNotOpen.Create('Called read on non-open pipe');
 
   result := 0;
   nRemaining := count;
+  pData := pBuf;
+  Inc( pData, offset);
   while nRemaining > 0 do begin
     overlapped := TOverlappedHelperImpl.Create;
 
      // read the data
-    bOk := ReadFile( FPipe, PByteArray(pBuf)^[offset], nRemaining, cbRead, overlapped.OverlappedPtr);
+    bOk := ReadFile( FPipe, pData^, nRemaining, cbRead, overlapped.OverlappedPtr);
     if not bOk then begin
       dwError := GetLastError;
       case dwError of
         ERROR_IO_PENDING : begin
           dwWait := overlapped.WaitFor(FTimeout);
 
-          if (dwWait = WAIT_TIMEOUT)
-          then raise TTransportExceptionTimedOut.Create('Pipe read timed out');
+          if (dwWait = WAIT_TIMEOUT) then begin
+            CancelIo( FPipe);  // prevents possible AV on invalid overlapped ptr
+            raise TTransportExceptionTimedOut.Create('Pipe read timed out');
+          end;
 
           if (dwWait <> WAIT_OBJECT_0)
           or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbRead, TRUE)
@@ -477,7 +493,7 @@
     ASSERT( cbRead > 0);  // see TTransportImpl.ReadAll()
     ASSERT( cbRead <= DWORD(nRemaining));
     Dec( nRemaining, cbRead);
-    Inc( offset, cbRead);
+    Inc( pData, cbRead);
     Inc( result, cbRead);
   end;
 end;
@@ -864,8 +880,10 @@
   CreateNamedPipe;
   while not FConnected do begin
 
-    if QueryStopServer
-    then Abort;
+    if QueryStopServer then begin
+      InternalClose;
+      Abort;
+    end;
 
     if Assigned(fnAccepting)
     then fnAccepting();
diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas
index 52b617b..dad9ab7 100644
--- a/lib/delphi/src/Thrift.Transport.pas
+++ b/lib/delphi/src/Thrift.Transport.pas
@@ -39,6 +39,7 @@
     {$ENDIF}
   {$ENDIF}
   Thrift.Collections,
+  Thrift.Exception,
   Thrift.Utils,
   Thrift.Stream;
 
@@ -79,7 +80,7 @@
     procedure Flush; virtual;
   end;
 
-  TTransportException = class( Exception )
+  TTransportException = class( TException)
   public
     type
       TExceptionType = (
@@ -117,14 +118,21 @@
   TTransportExceptionInterrupted = class (TTransportExceptionSpecialized);
 
   IHTTPClient = interface( ITransport )
-    ['{0F5DB8AB-710D-4338-AAC9-46B5734C5057}']
+    ['{BA142D12-8AE6-4B50-9E33-6B7843B21D73}']
+    procedure SetDnsResolveTimeout(const Value: Integer);
+    function GetDnsResolveTimeout: Integer;
     procedure SetConnectionTimeout(const Value: Integer);
     function GetConnectionTimeout: Integer;
+    procedure SetSendTimeout(const Value: Integer);
+    function GetSendTimeout: Integer;
     procedure SetReadTimeout(const Value: Integer);
     function GetReadTimeout: Integer;
     function GetCustomHeaders: IThriftDictionary<string,string>;
     procedure SendRequest;
+
+    property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
     property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
+    property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
     property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
     property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
   end;
@@ -134,7 +142,9 @@
     FUri : string;
     FInputStream : IThriftStream;
     FOutputStream : IThriftStream;
+    FDnsResolveTimeout : Integer;
     FConnectionTimeout : Integer;
+    FSendTimeout : Integer;
     FReadTimeout : Integer;
     FCustomHeaders : IThriftDictionary<string,string>;
 
@@ -147,13 +157,20 @@
     procedure Write( const pBuf : Pointer; off, len : Integer); override;
     procedure Flush; override;
 
+    procedure SetDnsResolveTimeout(const Value: Integer);
+    function GetDnsResolveTimeout: Integer;
     procedure SetConnectionTimeout(const Value: Integer);
     function GetConnectionTimeout: Integer;
+    procedure SetSendTimeout(const Value: Integer);
+    function GetSendTimeout: Integer;
     procedure SetReadTimeout(const Value: Integer);
     function GetReadTimeout: Integer;
+
     function GetCustomHeaders: IThriftDictionary<string,string>;
     procedure SendRequest;
+    property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
     property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
+    property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
     property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
     property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
   public
@@ -457,16 +474,17 @@
 
 { THTTPClientImpl }
 
-procedure THTTPClientImpl.Close;
-begin
-  FInputStream := nil;
-  FOutputStream := nil;
-end;
-
 constructor THTTPClientImpl.Create(const AUri: string);
 begin
   inherited Create;
   FUri := AUri;
+
+  // defaults according to MSDN
+  FDnsResolveTimeout := 0; // no timeout
+  FConnectionTimeout := 60 * 1000;
+  FSendTimeout       := 30 * 1000;
+  FReadTimeout       := 30 * 1000;
+
   FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
   FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
 end;
@@ -474,13 +492,18 @@
 function THTTPClientImpl.CreateRequest: IXMLHTTPRequest;
 var
   pair : TPair<string,string>;
+  srvHttp : IServerXMLHTTPRequest;
 begin
   {$IF CompilerVersion >= 21.0}
-  Result := CoXMLHTTP.Create;
+  Result := CoServerXMLHTTP.Create;
   {$ELSE}
   Result := CoXMLHTTPRequest.Create;
   {$IFEND}
 
+  // setting a timeout value to 0 (zero) means "no timeout" for that setting
+  if Supports( result, IServerXMLHTTPRequest, srvHttp)
+  then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
+
   Result.open('POST', FUri, False, '', '');
   Result.setRequestHeader( 'Content-Type', 'application/x-thrift');
   Result.setRequestHeader( 'Accept', 'application/x-thrift');
@@ -497,14 +520,14 @@
   inherited;
 end;
 
-procedure THTTPClientImpl.Flush;
+function THTTPClientImpl.GetDnsResolveTimeout: Integer;
 begin
-  try
-    SendRequest;
-  finally
-    FOutputStream := nil;
-    FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
-  end;
+  Result := FDnsResolveTimeout;
+end;
+
+procedure THTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
+begin
+  FDnsResolveTimeout := Value;
 end;
 
 function THTTPClientImpl.GetConnectionTimeout: Integer;
@@ -512,6 +535,31 @@
   Result := FConnectionTimeout;
 end;
 
+procedure THTTPClientImpl.SetConnectionTimeout(const Value: Integer);
+begin
+  FConnectionTimeout := Value;
+end;
+
+function THTTPClientImpl.GetSendTimeout: Integer;
+begin
+  Result := FSendTimeout;
+end;
+
+procedure THTTPClientImpl.SetSendTimeout(const Value: Integer);
+begin
+  FSendTimeout := Value;
+end;
+
+function THTTPClientImpl.GetReadTimeout: Integer;
+begin
+  Result := FReadTimeout;
+end;
+
+procedure THTTPClientImpl.SetReadTimeout(const Value: Integer);
+begin
+  FReadTimeout := Value;
+end;
+
 function THTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
 begin
   Result := FCustomHeaders;
@@ -522,14 +570,26 @@
   Result := True;
 end;
 
-function THTTPClientImpl.GetReadTimeout: Integer;
-begin
-  Result := FReadTimeout;
-end;
-
 procedure THTTPClientImpl.Open;
 begin
-  // nothing to do
+  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+end;
+
+procedure THTTPClientImpl.Close;
+begin
+  FInputStream := nil;
+  FOutputStream := nil;
+end;
+
+procedure THTTPClientImpl.Flush;
+begin
+  try
+    SendRequest;
+  finally
+    FOutputStream := nil;
+    FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+    ASSERT( FOutputStream <> nil);
+  end;
 end;
 
 function THTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
@@ -571,16 +631,6 @@
   end;
 end;
 
-procedure THTTPClientImpl.SetConnectionTimeout(const Value: Integer);
-begin
-  FConnectionTimeout := Value;
-end;
-
-procedure THTTPClientImpl.SetReadTimeout(const Value: Integer);
-begin
-  FReadTimeout := Value
-end;
-
 procedure THTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
 begin
   FOutputStream.Write( pBuf, off, len);
@@ -842,8 +892,13 @@
 procedure TSocketImpl.Close;
 begin
   inherited Close;
+
+  FInputStream := nil;
+  FOutputStream := nil;
+
   if FOwnsClient
-  then FreeAndNil( FClient);
+  then FreeAndNil( FClient)
+  else FClient := nil;
 end;
 
 function TSocketImpl.GetIsOpen: Boolean;
@@ -954,22 +1009,24 @@
 begin
   Result := (FWriteBuffer <> nil)
         and (FReadBuffer <> nil)
-        and (FStream <> nil);
+        and (FStream <> nil)
+        and FStream.IsOpen;
 end;
 
 procedure TBufferedStreamImpl.Open;
 begin
-  // nothing to do
+  FStream.Open;
 end;
 
 function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
 var
   nRead : Integer;
   tempbuf : TBytes;
+  pTmp : PByte;
 begin
   inherited;
   Result := 0;
-  
+
   if IsOpen then begin
     while count > 0 do begin
 
@@ -984,8 +1041,10 @@
       end;
 
       if FReadBuffer.Position < FReadBuffer.Size then begin
-        nRead  := Min( FReadBuffer.Size - FReadBuffer.Position, count);
-        Inc( Result, FReadBuffer.Read( PByteArray(pBuf)^[offset], nRead));
+        nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count);
+        pTmp  := pBuf;
+        Inc( pTmp, offset);
+        Inc( Result, FReadBuffer.Read( pTmp^, nRead));
         Dec( count, nRead);
         Inc( offset, nRead);
       end;
@@ -1011,11 +1070,14 @@
 end;
 
 procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
+var pTmp : PByte;
 begin
   inherited;
   if count > 0 then begin
     if IsOpen then begin
-      FWriteBuffer.Write( PByteArray(pBuf)^[offset], count );
+      pTmp := pBuf;
+      Inc( pTmp, offset);
+      FWriteBuffer.Write( pTmp^, count );
       if FWriteBuffer.Size > FBufSize then begin
         Flush;
       end;
@@ -1025,12 +1087,6 @@
 
 { TStreamTransportImpl }
 
-procedure TStreamTransportImpl.Close;
-begin
-  FInputStream := nil;
-  FOutputStream := nil;
-end;
-
 constructor TStreamTransportImpl.Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
 begin
   inherited Create;
@@ -1045,6 +1101,12 @@
   inherited;
 end;
 
+procedure TStreamTransportImpl.Close;
+begin
+  FInputStream := nil;
+  FOutputStream := nil;
+end;
+
 procedure TStreamTransportImpl.Flush;
 begin
   if FOutputStream = nil then begin
@@ -1066,7 +1128,7 @@
 
 function TStreamTransportImpl.GetOutputStream: IThriftStream;
 begin
-  Result := FInputStream;
+  Result := FOutputStream;
 end;
 
 procedure TStreamTransportImpl.Open;
@@ -1100,11 +1162,6 @@
   Create( ATransport, 1024 );
 end;
 
-procedure TBufferedTransportImpl.Close;
-begin
-  FTransport.Close;
-end;
-
 constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport;  ABufSize: Integer);
 begin
   inherited Create;
@@ -1113,6 +1170,13 @@
   InitBuffers;
 end;
 
+procedure TBufferedTransportImpl.Close;
+begin
+  FTransport.Close;
+  FInputBuffer := nil;
+  FOutputBuffer := nil;  
+end;
+
 procedure TBufferedTransportImpl.Flush;
 begin
   if FOutputBuffer <> nil then begin
@@ -1142,7 +1206,8 @@
 
 procedure TBufferedTransportImpl.Open;
 begin
-  FTransport.Open
+  FTransport.Open;
+  InitBuffers;  // we need to get the buffers to match FTransport substreams again
 end;
 
 function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
@@ -1254,12 +1319,16 @@
 end;
 
 function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
+var pTmp : PByte;
 begin
   if len > (buflen-off)
   then len := buflen-off;
 
+  pTmp := pBuf;
+  Inc( pTmp, off);
+
   if (FReadBuffer <> nil) and (len > 0) then begin
-    result := FReadBuffer.Read( PByteArray(pBuf)^[off], len);
+    result := FReadBuffer.Read( pTmp^, len);
     if result > 0 then begin
       Exit;
     end;
@@ -1267,7 +1336,7 @@
 
   ReadFrame;
   if len > 0
-  then Result := FReadBuffer.Read( PByteArray(pBuf)^[off], len)
+  then Result := FReadBuffer.Read( pTmp^, len)
   else Result := 0;
 end;
 
@@ -1294,9 +1363,14 @@
 end;
 
 procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
+var pTmp : PByte;
 begin
-  if len > 0
-  then FWriteBuffer.Write( PByteArray(pBuf)^[off], len );
+  if len > 0 then begin
+    pTmp := pBuf;
+    Inc( pTmp, off);
+
+    FWriteBuffer.Write( pTmp^, len );
+  end;
 end;
 
 { TFramedTransport.TFactory }
@@ -1482,7 +1556,7 @@
     wsaError,
     msecs : Integer;
     nBytes : Integer;
-    pDest : PByte;
+    pTmp : PByte;
 begin
   inherited;
 
@@ -1491,11 +1565,12 @@
   else msecs := DEFAULT_THRIFT_TIMEOUT;
 
   result := 0;
-  pDest := @(PByteArray(pBuf)^[offset]);
+  pTmp   := pBuf;
+  Inc( pTmp, offset);
   while count > 0 do begin
 
     while TRUE do begin
-      wfd := WaitForData( msecs, pDest, count, wsaError, nBytes);
+      wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes);
       case wfd of
         TWaitForData.wfd_Error    :  Exit;
         TWaitForData.wfd_HaveData :  Break;
@@ -1519,8 +1594,8 @@
     msecs := Max( msecs, 200);
 
     ASSERT( nBytes <= count);
-    nBytes := FTcpClient.ReceiveBuf( pDest^, nBytes);
-    Inc( pDest, nBytes);
+    nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes);
+    Inc( pTmp, nBytes);
     Dec( count, nBytes);
     Inc( result, nBytes);
   end;
@@ -1546,6 +1621,7 @@
 // old sockets version
 var bCanWrite, bError : Boolean;
     retval, wsaError : Integer;
+    pTmp : PByte;
 begin
   inherited;
 
@@ -1566,7 +1642,9 @@
   if bError or not bCanWrite
   then raise TTransportExceptionUnknown.Create('unknown error');
 
-  FTcpClient.SendBuf( PByteArray(pBuf)^[offset], count);
+  pTmp := pBuf;
+  Inc( pTmp, offset);
+  FTcpClient.SendBuf( pTmp^, count);
 end;
 
 {$ELSE}
@@ -1574,16 +1652,17 @@
 function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
 // new sockets version
 var nBytes : Integer;
-    pDest : PByte;
+    pTmp : PByte;
 begin
   inherited;
 
   result := 0;
-  pDest := @(PByteArray(pBuf)^[offset]);
+  pTmp   := pBuf;
+  Inc( pTmp, offset);
   while count > 0 do begin
-    nBytes := FTcpClient.Read(pDest^, count);
+    nBytes := FTcpClient.Read( pTmp^, count);
     if nBytes = 0 then Exit;
-    Inc( pDest, nBytes);
+    Inc( pTmp, nBytes);
     Dec( count, nBytes);
     Inc( result, nBytes);
   end;
@@ -1610,13 +1689,16 @@
 
 procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
 // new sockets version
+var pTmp : PByte;
 begin
   inherited;
 
   if not FTcpClient.IsOpen
   then raise TTransportExceptionNotOpen.Create('not open');
 
-  FTcpClient.Write( PByteArray(pBuf)^[offset], count);
+  pTmp := pBuf;
+  Inc( pTmp, offset);
+  FTcpClient.Write( pTmp^, count);
 end;
 
 {$ENDIF}
diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas
index 89d0211..7e57863 100644
--- a/lib/delphi/src/Thrift.Utils.pas
+++ b/lib/delphi/src/Thrift.Utils.pas
@@ -206,8 +206,12 @@
 
 class function CharUtils.IsHighSurrogate( const c : Char) : Boolean;
 begin
-  {$IF CompilerVersion < 23.0}
-  result := Character.IsHighSurrogate( c);
+  {$IF CompilerVersion < 25.0}
+    {$IFDEF OLD_UNIT_NAMES}
+    result := Character.IsHighSurrogate(c);
+    {$ELSE}
+    result := System.Character.IsHighSurrogate(c);
+    {$ENDIF}
   {$ELSE}
   result := c.IsHighSurrogate();
   {$IFEND}
@@ -216,10 +220,14 @@
 
 class function CharUtils.IsLowSurrogate( const c : Char) : Boolean;
 begin
-  {$IF CompilerVersion < 23.0}
-  result := Character.IsLowSurrogate( c);
+  {$IF CompilerVersion < 25.0}
+    {$IFDEF OLD_UNIT_NAMES}
+    result := Character.IsLowSurrogate(c);
+    {$ELSE}
+    result := System.Character.IsLowSurrogate(c);
+    {$ENDIF}
   {$ELSE}
-  result := c.IsLowSurrogate;
+  result := c.IsLowSurrogate();
   {$IFEND}
 end;
 
diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas
index edf20da..62481e7 100644
--- a/lib/delphi/src/Thrift.pas
+++ b/lib/delphi/src/Thrift.pas
@@ -22,15 +22,19 @@
 interface
 
 uses
-  SysUtils, Thrift.Protocol;
+  SysUtils,
+  Thrift.Exception,
+  Thrift.Protocol;
 
 const
-  Version = '0.11.0';
+  Version = '1.0.0';
 
 type
+  TException = Thrift.Exception.TException; // compatibility alias
+
   TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized;
 
-  TApplicationException = class( SysUtils.Exception )
+  TApplicationException = class( TException)
   public
     type
 {$SCOPEDENUMS ON}
@@ -83,31 +87,9 @@
   TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized);
   TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized);
 
-  // base class for IDL-generated exceptions
-  TException = class( SysUtils.Exception)
-  public
-    function Message : string;        // hide inherited property: allow read, but prevent accidental writes
-    procedure UpdateMessageProperty;  // update inherited message property with toString()
-  end;
 
 implementation
 
-{ TException }
-
-function TException.Message;
-// allow read (exception summary), but prevent accidental writes
-// read will return the exception summary
-begin
-  result := Self.ToString;
-end;
-
-procedure TException.UpdateMessageProperty;
-// Update the inherited Message property to better conform to standard behaviour.
-// Nice benefit: The IDE is now able to show the exception message again.
-begin
-  inherited Message := Self.ToString;  // produces a summary text
-end;
-
 { TApplicationException }
 
 function TApplicationException.GetType: TExceptionType;
diff --git a/lib/delphi/src/Thrift.Console.pas b/lib/delphi/test/ConsoleHelper.pas
similarity index 95%
rename from lib/delphi/src/Thrift.Console.pas
rename to lib/delphi/test/ConsoleHelper.pas
index 1dbb309..0a8ddcf 100644
--- a/lib/delphi/src/Thrift.Console.pas
+++ b/lib/delphi/test/ConsoleHelper.pas
@@ -17,7 +17,7 @@
  * under the License.
  *)
 
-unit Thrift.Console;
+unit ConsoleHelper;
 
 interface
 
@@ -99,10 +99,9 @@
   begin
     idx := FMemo.Count - 1;
     if idx < 0 then
-    begin
-      FMemo.Add( S );
-    end;
-    FMemo[idx] := FMemo[idx] + S;
+      FMemo.Add( S )
+    else
+      FMemo[idx] := FMemo[idx] + S;
   end;
   FLineBreak := bWriteLine;
 end;
diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas
index 59b2a66..0fa43b0 100644
--- a/lib/delphi/test/TestClient.pas
+++ b/lib/delphi/test/TestClient.pas
@@ -25,13 +25,19 @@
 {.$DEFINE PerfTest}     // activate the performance test
 {$DEFINE Exceptions}    // activate the exceptions test (or disable while debugging)
 
+{$if CompilerVersion >= 28}
+{$DEFINE SupportsAsync}
+{$ifend}
+
 interface
 
 uses
-  Windows, SysUtils, Classes, Math,
+  Windows, SysUtils, Classes, Math, ComObj, ActiveX,
+  {$IFDEF SupportsAsync} System.Threading, {$ENDIF}
   DateUtils,
   Generics.Collections,
   TestConstants,
+  ConsoleHelper,
   Thrift,
   Thrift.Protocol.Compact,
   Thrift.Protocol.JSON,
@@ -41,8 +47,7 @@
   Thrift.Stream,
   Thrift.Test,
   Thrift.Utils,
-  Thrift.Collections,
-  Thrift.Console;
+  Thrift.Collections;
 
 type
   TThreadConsole = class
@@ -54,6 +59,17 @@
     constructor Create( AThread: TThread);
   end;
 
+  TTestSetup = record
+    protType  : TKnownProtocol;
+    endpoint  : TEndpointTransport;
+    layered   : TLayeredTransports;
+    useSSL    : Boolean; // include where appropriate (TLayeredTransport?)
+    host      : string;
+    port      : Integer;
+    sPipeName : string;
+    hAnonRead, hAnonWrite : THandle;
+  end;
+
   TClientThread = class( TThread )
   private type
     TTestGroup = (
@@ -66,7 +82,15 @@
     );
     TTestGroups = set of TTestGroup;
 
+    TTestSize = (
+      Empty,           // Edge case: the zero-length empty binary
+      Normal,          // Fairly small array of usual size (256 bytes)
+      ByteArrayTest,   // THRIFT-4454 Large writes/reads may cause range check errors in debug mode
+      PipeWriteLimit   // THRIFT-4372 Pipe write operations across a network are limited to 65,535 bytes per write.
+    );
+
   private
+    FSetup : TTestSetup;
     FTransport : ITransport;
     FProtocol : IProtocol;
     FNumIteration : Integer;
@@ -85,18 +109,25 @@
     function  CalculateExitCode : Byte;
 
     procedure ClientTest;
+    {$IFDEF SupportsAsync}
+    procedure ClientAsyncTest;
+    {$ENDIF}
+
+    procedure InitializeProtocolTransportStack;
+    procedure ShutdownProtocolTransportStack;
+
     procedure JSONProtocolReadWriteTest;
-    function  PrepareBinaryData( aRandomDist, aHuge : Boolean) : TBytes;
+    function  PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes;
     {$IFDEF StressTest}
     procedure StressTest(const client : TThriftTest.Iface);
     {$ENDIF}
     {$IFDEF Win64}
-	procedure UseInterlockedExchangeAdd64;
+    procedure UseInterlockedExchangeAdd64;
     {$ENDIF}
   protected
     procedure Execute; override;
   public
-    constructor Create( const ATransport: ITransport; const AProtocol : IProtocol; ANumIteration: Integer);
+    constructor Create( const aSetup : TTestSetup; const aNumIteration: Integer);
     destructor Destroy; override;
   end;
 
@@ -177,38 +208,27 @@
 class function TTestClient.Execute(const args: array of string) : Byte;
 var
   i : Integer;
-  host : string;
-  port : Integer;
-  sPipeName : string;
-  hAnonRead, hAnonWrite : THandle;
+  threadExitCode : Byte;
   s : string;
   threads : array of TThread;
   dtStart : TDateTime;
   test : Integer;
   thread : TThread;
-  trans : ITransport;
-  prot : IProtocol;
-  streamtrans : IStreamTransport;
-  http : IHTTPClient;
-  protType : TKnownProtocol;
-  endpoint : TEndpointTransport;
-  layered : TLayeredTransports;
-  UseSSL : Boolean; // include where appropriate (TLayeredTransport?)
-const
-  // pipe timeouts to be used
-  DEBUG_TIMEOUT   = 30 * 1000;
-  RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT;
-  TIMEOUT         = RELEASE_TIMEOUT;
+  setup : TTestSetup;
 begin
-  protType := prot_Binary;
-  endpoint := trns_Sockets;
-  layered := [];
-  UseSSL := FALSE;
-  host := 'localhost';
-  port := 9090;
-  sPipeName := '';
-  hAnonRead := INVALID_HANDLE_VALUE;
-  hAnonWrite := INVALID_HANDLE_VALUE;
+  // init record
+  with setup do begin
+    protType   := prot_Binary;
+    endpoint   := trns_Sockets;
+    layered    := [];
+    useSSL     := FALSE;
+    host       := 'localhost';
+    port       := 9090;
+    sPipeName  := '';
+    hAnonRead  := INVALID_HANDLE_VALUE;
+    hAnonWrite := INVALID_HANDLE_VALUE;
+  end;
+
   try
     i := 0;
     while ( i < Length(args) ) do begin
@@ -223,15 +243,15 @@
       end
       else if s = '--host' then begin
         // --host arg (=localhost)     Host to connect
-        host := args[i];
+        setup.host := args[i];
         Inc( i);
       end
       else if s = '--port' then begin
         // --port arg (=9090)          Port number to connect
         s := args[i];
         Inc( i);
-        port := StrToIntDef(s,0);
-        if port <= 0 then InvalidArgs;
+        setup.port := StrToIntDef(s,0);
+        if setup.port <= 0 then InvalidArgs;
       end
       else if s = '--domain-socket' then begin
         // --domain-socket arg         Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port
@@ -239,27 +259,29 @@
       end
       else if s = '--named-pipe' then begin
         // --named-pipe arg            Windows Named Pipe (e.g. MyThriftPipe)
-        endpoint := trns_NamedPipes;
-        sPipeName := args[i];
+        setup.endpoint := trns_NamedPipes;
+        setup.sPipeName := args[i];
         Inc( i);
+        Console.WriteLine('Using named pipe ('+setup.sPipeName+')');
       end
       else if s = '--anon-pipes' then begin
         // --anon-pipes hRead hWrite   Windows Anonymous Pipes pair (handles)
-        endpoint := trns_AnonPipes;
-        hAnonRead := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE)));
+        setup.endpoint := trns_AnonPipes;
+        setup.hAnonRead := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE)));
         Inc( i);
-        hAnonWrite := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE)));
+        setup.hAnonWrite := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE)));
         Inc( i);
+        Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(setup.hAnonRead))+' and '+IntToStr(Integer(setup.hAnonWrite))+')');
       end
       else if s = '--transport' then begin
         // --transport arg (=sockets)  Transport: buffered, framed, http, evhttp
         s := args[i];
         Inc( i);
 
-        if      s = 'buffered' then Include( layered, trns_Buffered)
-        else if s = 'framed'   then Include( layered, trns_Framed)
-        else if s = 'http'     then endpoint := trns_Http
-        else if s = 'evhttp'   then endpoint := trns_EvHttp
+        if      s = 'buffered' then Include( setup.layered, trns_Buffered)
+        else if s = 'framed'   then Include( setup.layered, trns_Framed)
+        else if s = 'http'     then setup.endpoint := trns_Http
+        else if s = 'evhttp'   then setup.endpoint := trns_EvHttp
         else InvalidArgs;
       end
       else if s = '--protocol' then begin
@@ -267,14 +289,14 @@
         s := args[i];
         Inc( i);
 
-        if      s = 'binary'   then protType := prot_Binary
-        else if s = 'compact'  then protType := prot_Compact
-        else if s = 'json'     then protType := prot_JSON
+        if      s = 'binary'   then setup.protType := prot_Binary
+        else if s = 'compact'  then setup.protType := prot_Compact
+        else if s = 'json'     then setup.protType := prot_JSON
         else InvalidArgs;
       end
       else if s = '--ssl' then begin
         // --ssl                       Encrypted Transport using SSL
-        UseSSL := TRUE;
+        setup.useSSL := TRUE;
 
       end
       else if (s = '-n') or (s = '--testloops') then begin
@@ -300,7 +322,7 @@
 
     // In the anonymous pipes mode the client is launched by the test server
     // -> behave nicely and allow for attaching a debugger to this process
-    if (endpoint = trns_AnonPipes) and not IsDebuggerPresent
+    if (setup.endpoint = trns_AnonPipes) and not IsDebuggerPresent
     then MessageBox( 0, 'Attach Debugger and/or click OK to continue.',
                         'Thrift TestClient (Delphi)',
                         MB_OK or MB_ICONEXCLAMATION);
@@ -308,78 +330,30 @@
     SetLength( threads, FNumThread);
     dtStart := Now;
 
-    for test := 0 to FNumThread - 1 do
-    begin
-      case endpoint of
-        trns_Sockets: begin
-          Console.WriteLine('Using sockets ('+host+' port '+IntToStr(port)+')');
-          streamtrans := TSocketImpl.Create( host, port );
-        end;
+    // layered transports are not really meant to be stacked upon each other
+    if (trns_Framed in setup.layered) then begin
+      Console.WriteLine('Using framed transport');
+    end
+    else if (trns_Buffered in setup.layered) then begin
+      Console.WriteLine('Using buffered transport');
+    end;
 
-        trns_Http: begin
-          Console.WriteLine('Using HTTPClient');
-          http := THTTPClientImpl.Create( host);
-          trans := http;
-        end;
+    Console.WriteLine(THRIFT_PROTOCOLS[setup.protType]+' protocol');
 
-        trns_EvHttp: begin
-          raise Exception.Create(ENDPOINT_TRANSPORTS[endpoint]+' transport not implemented');
-        end;
-
-        trns_NamedPipes: begin
-          Console.WriteLine('Using named pipe ('+sPipeName+')');
-          streamtrans := TNamedPipeTransportClientEndImpl.Create( sPipeName, 0, nil, TIMEOUT, TIMEOUT);
-        end;
-
-        trns_AnonPipes: begin
-          Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(hAnonRead))+' and '+IntToStr(Integer(hAnonWrite))+')');
-          streamtrans := TAnonymousPipeTransportImpl.Create( hAnonRead, hAnonWrite, FALSE);
-        end;
-
-      else
-        raise Exception.Create('Unhandled endpoint transport');
-      end;
-      trans := streamtrans;
-      ASSERT( trans <> nil);
-
-      if (trns_Buffered in layered) then begin
-        trans := TBufferedTransportImpl.Create( streamtrans, 32);  // small buffer to test read()
-        Console.WriteLine('Using buffered transport');
-      end;
-
-      if (trns_Framed in layered) then begin
-        trans := TFramedTransportImpl.Create( trans );
-        Console.WriteLine('Using framed transport');
-      end;
-
-      if UseSSL then begin
-        raise Exception.Create('SSL not implemented');
-      end;
-
-      // create protocol instance, default to BinaryProtocol
-      case protType of
-        prot_Binary  :  prot := TBinaryProtocolImpl.Create( trans, BINARY_STRICT_READ, BINARY_STRICT_WRITE);
-        prot_JSON    :  prot := TJSONProtocolImpl.Create( trans);
-        prot_Compact :  prot := TCompactProtocolImpl.Create( trans);
-      else
-        raise Exception.Create('Unhandled protocol');
-      end;
-      ASSERT( trans <> nil);
-      Console.WriteLine(THRIFT_PROTOCOLS[protType]+' protocol');
-
-      thread := TClientThread.Create( trans, prot, FNumIteration);
+    for test := 0 to FNumThread - 1 do begin
+      thread := TClientThread.Create( setup, FNumIteration);
       threads[test] := thread;
       thread.Start;
     end;
 
     result := 0;
     for test := 0 to FNumThread - 1 do begin
-      result := result or threads[test].WaitFor;
+      threadExitCode := threads[test].WaitFor;
+      result := result or threadExitCode;
+      threads[test].Free;
+      threads[test] := nil;
     end;
 
-    for test := 0 to FNumThread - 1
-    do threads[test].Free;
-
     Console.Write('Total time: ' + IntToStr( MilliSecondsBetween(Now, dtStart)));
 
   except
@@ -455,6 +429,7 @@
   first_map : IThriftDictionary<TNumberz, IInsanity>;
   second_map : IThriftDictionary<TNumberz, IInsanity>;
   pair : TPair<TNumberz, TUserId>;
+  testsize : TTestSize;
 begin
   client := TThriftTest.TClient.Create( FProtocol);
   FTransport.Open;
@@ -480,7 +455,7 @@
       Console.WriteLine( ' = ' + IntToStr(e.ErrorCode) + ', ' + e.Message_ );
     end;
     on e:TTransportException do Expect( FALSE, 'Unexpected : "'+e.ToString+'"');
-    on e:Exception do Expect( FALSE, 'Unexpected exception type "'+e.ClassName+'"');
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
 
   // case 2: exception type NOT declared in IDL at the function call
@@ -495,8 +470,8 @@
     on e:TApplicationException do begin
       Console.WriteLine( e.ClassName+' = '+e.Message); // this is what we get
     end;
-    on e:TException do Expect( FALSE, 'Unexpected exception type "'+e.ClassName+'"');
-    on e:Exception do Expect( FALSE, 'Unexpected exception type "'+e.ClassName+'"');
+    on e:TException do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
 
 
@@ -510,7 +485,7 @@
     Expect( TRUE, 'testException(''something''): must not trow an exception');
   except
     on e:TTransportException do Expect( FALSE, 'Unexpected : "'+e.ToString+'"');
-    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
   {$ENDIF Exceptions}
 
@@ -547,42 +522,18 @@
   Expect( i64 = -34359738368, 'testI64(-34359738368) = ' + IntToStr( i64));
 
   // random binary small
-  binOut := PrepareBinaryData( TRUE, FALSE);
-  Console.WriteLine('testBinary('+BytesToHex(binOut)+')');
-  try
-    binIn := client.testBinary(binOut);
-    Expect( Length(binOut) = Length(binIn), 'testBinary(): length '+IntToStr(Length(binOut))+' = '+IntToStr(Length(binIn)));
-    i32 := Min( Length(binOut), Length(binIn));
-    Expect( CompareMem( binOut, binIn, i32), 'testBinary('+BytesToHex(binOut)+') = '+BytesToHex(binIn));
-  except
-    on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message);
-    on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message);
-  end;
-
-  // random binary huge
-  binOut := PrepareBinaryData( TRUE, TRUE);
-  Console.WriteLine('testBinary('+BytesToHex(binOut)+')');
-  try
-    binIn := client.testBinary(binOut);
-    Expect( Length(binOut) = Length(binIn), 'testBinary(): length '+IntToStr(Length(binOut))+' = '+IntToStr(Length(binIn)));
-    i32 := Min( Length(binOut), Length(binIn));
-    Expect( CompareMem( binOut, binIn, i32), 'testBinary('+BytesToHex(binOut)+') = '+BytesToHex(binIn));
-  except
-    on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message);
-    on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message);
-  end;
-
-  // empty binary
-  SetLength( binOut, 0);
-  Console.WriteLine('testBinary('+BytesToHex(binOut)+')');
-  try
-    binIn := client.testBinary(binOut);
-    Expect( Length(binOut) = Length(binIn), 'testBinary(): length '+IntToStr(Length(binOut))+' = '+IntToStr(Length(binIn)));
-    i32 := Min( Length(binOut), Length(binIn));
-    Expect( CompareMem( binOut, binIn, i32), 'testBinary('+BytesToHex(binOut)+') = '+BytesToHex(binIn));
-  except
-    on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message);
-    on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message);
+  for testsize := Low(TTestSize) to High(TTestSize) do begin
+    binOut := PrepareBinaryData( TRUE, testsize);
+    Console.WriteLine('testBinary('+BytesToHex(binOut)+')');
+    try
+      binIn := client.testBinary(binOut);
+      Expect( Length(binOut) = Length(binIn), 'testBinary(): length '+IntToStr(Length(binOut))+' = '+IntToStr(Length(binIn)));
+      i32 := Min( Length(binOut), Length(binIn));
+      Expect( CompareMem( binOut, binIn, i32), 'testBinary('+BytesToHex(binOut)+') = '+BytesToHex(binIn));
+    except
+      on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message);
+      on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message);
+    end;
   end;
 
   Console.WriteLine('testDouble(5.325098235)');
@@ -945,7 +896,7 @@
     Expect( not i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing));
     }
   except
-    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
 
   StartTestGroup( 'testMultiException(Xception)', test_Exceptions);
@@ -959,7 +910,7 @@
       Expect( x.ErrorCode = 1001, 'x.ErrorCode = '+IntToStr(x.ErrorCode));
       Expect( x.Message_ = 'This is an Xception', 'x.Message = "'+x.Message_+'"');
     end;
-    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
 
   StartTestGroup( 'testMultiException(Xception2)', test_Exceptions);
@@ -979,7 +930,7 @@
       Expect( not x.Struct_thing.__isset_I64_thing, 'x.Struct_thing.__isset_I64_thing = '+BoolToString(x.Struct_thing.__isset_I64_thing));
       }
     end;
-    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
+    on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message);
   end;
 
 
@@ -1004,6 +955,33 @@
 end;
 
 
+{$IFDEF SupportsAsync}
+procedure TClientThread.ClientAsyncTest;
+var
+  client : TThriftTest.IAsync;
+  s : string;
+  i8 : ShortInt;
+begin
+  StartTestGroup( 'Async Tests', test_Unknown);
+  client := TThriftTest.TClient.Create( FProtocol);
+  FTransport.Open;
+
+  // oneway void functions
+  client.testOnewayAsync(1).Wait;
+  Expect( TRUE, 'Test Oneway(1)');  // success := no exception
+
+  // normal functions
+  s := client.testStringAsync(HUGE_TEST_STRING).Value;
+  Expect( length(s) = length(HUGE_TEST_STRING),
+          'testString( length(HUGE_TEST_STRING) = '+IntToStr(Length(HUGE_TEST_STRING))+') '
+         +'=> length(result) = '+IntToStr(Length(s)));
+
+  i8 := client.testByte(1).Value;
+  Expect( i8 = 1, 'testByte(1) = ' + IntToStr( i8 ));
+end;
+{$ENDIF}
+
+
 {$IFDEF StressTest}
 procedure TClientThread.StressTest(const client : TThriftTest.Iface);
 begin
@@ -1024,18 +1002,25 @@
 {$ENDIF}
 
 
-function TClientThread.PrepareBinaryData( aRandomDist, aHuge : Boolean) : TBytes;
+function TClientThread.PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes;
 var i : Integer;
 begin
-  if aHuge
-  then SetLength( result, $12345)  // tests for THRIFT-4372
-  else SetLength( result, $100);
+  case aSize of
+    Empty          : SetLength( result, 0);
+    Normal         : SetLength( result, $100);
+    ByteArrayTest  : SetLength( result, SizeOf(TByteArray) + 128);
+    PipeWriteLimit : SetLength( result, 65535 + 128);
+  else
+    raise EArgumentException.Create('aSize');
+  end;
+
   ASSERT( Low(result) = 0);
+  if Length(result) = 0 then Exit;
 
   // linear distribution, unless random is requested
   if not aRandomDist then begin
     for i := Low(result) to High(result) do begin
-      result[i] := i;
+      result[i] := i mod $100;
     end;
     Exit;
   end;
@@ -1090,7 +1075,7 @@
     StartTestGroup( 'JsonProtocolTest', test_Unknown);
 
     // prepare binary data
-    binary := PrepareBinaryData( FALSE, FALSE);
+    binary := PrepareBinaryData( FALSE, Normal);
     SetLength( emptyBinary, 0); // empty binary data block
 
     // output setup
@@ -1272,12 +1257,11 @@
 end;
 
 
-constructor TClientThread.Create( const ATransport: ITransport; const AProtocol : IProtocol; ANumIteration: Integer);
+constructor TClientThread.Create( const aSetup : TTestSetup; const aNumIteration: Integer);
 begin
-  inherited Create( True );
+  FSetup := aSetup;
   FNumIteration := ANumIteration;
-  FTransport := ATransport;
-  FProtocol := AProtocol;
+
   FConsole := TThreadConsole.Create( Self );
   FCurrentTest := test_Unknown;
 
@@ -1285,6 +1269,8 @@
   FErrors := TStringList.Create;
   FErrors.Sorted := FALSE;
   FErrors.Duplicates := dupAccept;
+
+  inherited Create( TRUE);
 end;
 
 destructor TClientThread.Destroy;
@@ -1297,38 +1283,136 @@
 procedure TClientThread.Execute;
 var
   i : Integer;
-  proc : TThreadProcedure;
 begin
   // perform all tests
   try
-    {$IFDEF Win64}  
+    {$IFDEF Win64}
     UseInterlockedExchangeAdd64;
-	{$ENDIF}
+    {$ENDIF}
     JSONProtocolReadWriteTest;
-	
-    for i := 0 to FNumIteration - 1 do
-    begin
-      ClientTest;
+
+    // must be run in the context of the thread
+    InitializeProtocolTransportStack;
+    try
+      for i := 0 to FNumIteration - 1 do begin
+        ClientTest;
+        {$IFDEF SupportsAsync}
+        ClientAsyncTest;
+        {$ENDIF}
+      end;
+
+      // report the outcome
+      ReportResults;
+      SetReturnValue( CalculateExitCode);
+
+    finally
+      ShutdownProtocolTransportStack;
     end;
+
   except
     on e:Exception do Expect( FALSE, 'unexpected exception: "'+e.message+'"');
   end;
+end;
 
-  // report the outcome
-  ReportResults;
-  SetReturnValue( CalculateExitCode);
 
-  // shutdown
-  proc := procedure
-  begin
-    if FTransport <> nil then
-    begin
+procedure TClientThread.InitializeProtocolTransportStack;
+var
+  streamtrans : IStreamTransport;
+  http : IHTTPClient;
+  sUrl : string;
+const
+  DEBUG_TIMEOUT   = 30 * 1000;
+  RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT;
+  PIPE_TIMEOUT    = RELEASE_TIMEOUT;
+  HTTP_TIMEOUTS   = 10 * 1000;
+begin
+  // needed for HTTP clients as they utilize the MSXML COM components
+  OleCheck( CoInitialize( nil));
+
+  case FSetup.endpoint of
+    trns_Sockets: begin
+      Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')');
+      streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port );
+      FTransport := streamtrans;
+    end;
+
+    trns_Http: begin
+      Console.WriteLine('Using HTTPClient');
+      if FSetup.useSSL
+      then sUrl := 'http://'
+      else sUrl := 'https://';
+      sUrl := sUrl + FSetup.host;
+      case FSetup.port of
+        80  : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+        443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+      else
+        if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+      end;
+      http := THTTPClientImpl.Create( sUrl);
+      http.DnsResolveTimeout := HTTP_TIMEOUTS;
+      http.ConnectionTimeout := HTTP_TIMEOUTS;
+      http.SendTimeout       := HTTP_TIMEOUTS;
+      http.ReadTimeout       := HTTP_TIMEOUTS;
+      FTransport := http;
+    end;
+
+    trns_EvHttp: begin
+      raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' transport not implemented');
+    end;
+
+    trns_NamedPipes: begin
+      streamtrans := TNamedPipeTransportClientEndImpl.Create( FSetup.sPipeName, 0, nil, PIPE_TIMEOUT, PIPE_TIMEOUT);
+      FTransport := streamtrans;
+    end;
+
+    trns_AnonPipes: begin
+      streamtrans := TAnonymousPipeTransportImpl.Create( FSetup.hAnonRead, FSetup.hAnonWrite, FALSE);
+      FTransport := streamtrans;
+    end;
+
+  else
+    raise Exception.Create('Unhandled endpoint transport');
+  end;
+  ASSERT( FTransport <> nil);
+
+  // layered transports are not really meant to be stacked upon each other
+  if (trns_Framed in FSetup.layered) then begin
+    FTransport := TFramedTransportImpl.Create( FTransport);
+  end
+  else if (trns_Buffered in FSetup.layered) and (streamtrans <> nil) then begin
+    FTransport := TBufferedTransportImpl.Create( streamtrans, 32);  // small buffer to test read()
+  end;
+
+  if FSetup.useSSL then begin
+    raise Exception.Create('SSL/TLS not implemented');
+  end;
+
+  // create protocol instance, default to BinaryProtocol
+  case FSetup.protType of
+    prot_Binary  :  FProtocol := TBinaryProtocolImpl.Create( FTransport, BINARY_STRICT_READ, BINARY_STRICT_WRITE);
+    prot_JSON    :  FProtocol := TJSONProtocolImpl.Create( FTransport);
+    prot_Compact :  FProtocol := TCompactProtocolImpl.Create( FTransport);
+  else
+    raise Exception.Create('Unhandled protocol');
+  end;
+
+  ASSERT( (FTransport <> nil) and (FProtocol <> nil));
+end;
+
+
+procedure TClientThread.ShutdownProtocolTransportStack;
+begin
+  try
+    FProtocol := nil;
+
+    if FTransport <> nil then begin
       FTransport.Close;
       FTransport := nil;
     end;
-  end;
 
-  Synchronize( proc );
+  finally
+    CoUninitialize;
+  end;
 end;
 
 
diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas
index 97041d0..69cb175 100644
--- a/lib/delphi/test/TestServer.pas
+++ b/lib/delphi/test/TestServer.pas
@@ -29,7 +29,6 @@
 uses
   Windows, SysUtils,
   Generics.Collections,
-  Thrift.Console,
   Thrift.Server,
   Thrift.Transport,
   Thrift.Transport.Pipes,
@@ -42,6 +41,7 @@
   Thrift,
   TestConstants,
   TestServerEvents,
+  ConsoleHelper,
   Contnrs;
 
 type
@@ -164,7 +164,7 @@
 
   if (arg = 'TException') then
   begin
-    raise TException.Create('');
+    raise TException.Create('TException');
   end;
 
   // else do not throw anything
diff --git a/lib/delphi/test/TestServerEvents.pas b/lib/delphi/test/TestServerEvents.pas
index 2e776d2..2208cd4 100644
--- a/lib/delphi/test/TestServerEvents.pas
+++ b/lib/delphi/test/TestServerEvents.pas
@@ -27,7 +27,7 @@
   Thrift.Protocol,
   Thrift.Transport,
   Thrift.Server,
-  Thrift.Console;
+  ConsoleHelper;
 
 type
   TRequestEventsImpl = class( TInterfacedObject, IRequestEvents)
diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr
index f2e5250..06dbd3d 100644
--- a/lib/delphi/test/client.dpr
+++ b/lib/delphi/test/client.dpr
@@ -29,6 +29,7 @@
   Thrift in '..\src\Thrift.pas',
   Thrift.Transport in '..\src\Thrift.Transport.pas',
   Thrift.Socket in '..\src\Thrift.Socket.pas',
+  Thrift.Exception in '..\src\Thrift.Exception.pas',
   Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas',
   Thrift.Protocol in '..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas',
@@ -37,7 +38,6 @@
   Thrift.Collections in '..\src\Thrift.Collections.pas',
   Thrift.Server in '..\src\Thrift.Server.pas',
   Thrift.Stream in '..\src\Thrift.Stream.pas',
-  Thrift.Console in '..\src\Thrift.Console.pas',
   Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas',
   Thrift.Utils in '..\src\Thrift.Utils.pas';
 
diff --git a/test/go/src/bin/testclient/pre_go17.go b/lib/delphi/test/keywords/ReservedIncluded.thrift
similarity index 84%
rename from test/go/src/bin/testclient/pre_go17.go
rename to lib/delphi/test/keywords/ReservedIncluded.thrift
index 10a6fb8..8b47a50 100644
--- a/test/go/src/bin/testclient/pre_go17.go
+++ b/lib/delphi/test/keywords/ReservedIncluded.thrift
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,8 +17,9 @@
  * under the License.
  */
 
-package main
+// make sure generated code does not produce name collisions with predefined keywords
+namespace delphi SysUtils
 
-import "golang.org/x/net/context"
+const i32 integer = 42
 
-var defaultCtx = context.Background()
+// EOF
diff --git a/lib/delphi/test/keywords/ReservedKeywords.dpr b/lib/delphi/test/keywords/ReservedKeywords.dpr
new file mode 100644
index 0000000..1fbc8c1
--- /dev/null
+++ b/lib/delphi/test/keywords/ReservedKeywords.dpr
@@ -0,0 +1,15 @@
+program ReservedKeywords;
+
+{$APPTYPE CONSOLE}
+
+uses
+  SysUtils, System_;
+
+begin
+  try
+    { TODO -oUser -cConsole Main : Code hier einfügen }
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.
diff --git a/lib/delphi/test/keywords/ReservedKeywords.dproj b/lib/delphi/test/keywords/ReservedKeywords.dproj
new file mode 100644
index 0000000..6bd9544
--- /dev/null
+++ b/lib/delphi/test/keywords/ReservedKeywords.dproj
@@ -0,0 +1,112 @@
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+		<PropertyGroup>
+			<ProjectGuid>{F2E9B6FC-A931-4271-8E30-5A4E402481B4}</ProjectGuid>
+			<MainSource>ReservedKeywords.dpr</MainSource>
+			<ProjectVersion>12.3</ProjectVersion>
+			<Basis>True</Basis>
+			<Config Condition="'$(Config)'==''">Debug</Config>
+			<Platform>Win32</Platform>
+			<AppType>Console</AppType>
+			<FrameworkType>None</FrameworkType>
+			<DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''">
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+			<Cfg_1>true</Cfg_1>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+			<Cfg_2>true</Cfg_2>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Base)'!=''">
+			<DCC_ImageBase>00400000</DCC_ImageBase>
+			<DCC_DcuOutput>.\$(Config)\$(Platform)</DCC_DcuOutput>
+			<DCC_UnitSearchPath>gen-delphi;..\..\src;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
+			<DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
+			<DCC_ExeOutput>.\$(Config)\$(Platform)</DCC_ExeOutput>
+			<DCC_N>false</DCC_N>
+			<DCC_S>false</DCC_S>
+			<DCC_K>false</DCC_K>
+			<DCC_E>false</DCC_E>
+			<DCC_F>false</DCC_F>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_1)'!=''">
+			<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+			<DCC_Optimize>false</DCC_Optimize>
+			<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_2)'!=''">
+			<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+			<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+			<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+			<DCC_DebugInformation>false</DCC_DebugInformation>
+		</PropertyGroup>
+		<ItemGroup>
+			<DelphiCompile Include="ReservedKeywords.dpr">
+				<MainSource>MainSource</MainSource>
+			</DelphiCompile>
+			<BuildConfiguration Include="Release">
+				<Key>Cfg_2</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Basis">
+				<Key>Base</Key>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Debug">
+				<Key>Cfg_1</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+		</ItemGroup>
+		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
+		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
+		<PropertyGroup>
+			<PreBuildEvent><![CDATA[thrift -r  -gen delphi ReservedKeywords.thrift]]></PreBuildEvent>
+		</PropertyGroup>
+		<ProjectExtensions>
+			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
+			<Borland.ProjectType/>
+			<BorlandProject>
+				<Delphi.Personality>
+					<VersionInfo>
+						<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+						<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+						<VersionInfo Name="MajorVer">1</VersionInfo>
+						<VersionInfo Name="MinorVer">0</VersionInfo>
+						<VersionInfo Name="Release">0</VersionInfo>
+						<VersionInfo Name="Build">0</VersionInfo>
+						<VersionInfo Name="Debug">False</VersionInfo>
+						<VersionInfo Name="PreRelease">False</VersionInfo>
+						<VersionInfo Name="Special">False</VersionInfo>
+						<VersionInfo Name="Private">False</VersionInfo>
+						<VersionInfo Name="DLL">False</VersionInfo>
+						<VersionInfo Name="Locale">1031</VersionInfo>
+						<VersionInfo Name="CodePage">1252</VersionInfo>
+					</VersionInfo>
+					<VersionInfoKeys>
+						<VersionInfoKeys Name="CompanyName"/>
+						<VersionInfoKeys Name="FileDescription"/>
+						<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="InternalName"/>
+						<VersionInfoKeys Name="LegalCopyright"/>
+						<VersionInfoKeys Name="LegalTrademarks"/>
+						<VersionInfoKeys Name="OriginalFilename"/>
+						<VersionInfoKeys Name="ProductName"/>
+						<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="Comments"/>
+					</VersionInfoKeys>
+					<Source>
+						<Source Name="MainSource">ReservedKeywords.dpr</Source>
+					</Source>
+				</Delphi.Personality>
+				<Platforms>
+					<Platform value="Win32">True</Platform>
+				</Platforms>
+			</BorlandProject>
+			<ProjectFileVersion>12</ProjectFileVersion>
+		</ProjectExtensions>
+	</Project>
diff --git a/lib/delphi/test/codegen/ReservedKeywords.thrift b/lib/delphi/test/keywords/ReservedKeywords.thrift
similarity index 75%
rename from lib/delphi/test/codegen/ReservedKeywords.thrift
rename to lib/delphi/test/keywords/ReservedKeywords.thrift
index 8db3ea5..2f49d74 100644
--- a/lib/delphi/test/codegen/ReservedKeywords.thrift
+++ b/lib/delphi/test/keywords/ReservedKeywords.thrift
@@ -18,7 +18,9 @@
  */
 
 // make sure generated code does not produce name collisions with predefined keywords
+namespace delphi System
 
+include "ReservedIncluded.thrift"
 
 
 typedef i32 Cardinal
@@ -98,3 +100,39 @@
 }
 
 
+typedef i32 IProtocol 
+typedef i32 ITransport
+typedef i32 IFace
+typedef i32 IAsync
+typedef i32 System
+typedef i32 SysUtils
+typedef i32 Generics
+typedef i32 Thrift
+
+struct Struct_Thrift_Names {
+  1: IProtocol   IProtocol
+  2: ITransport  ITransport
+  3: IFace       IFace
+  4: IAsync      IAsync
+  5: System      System
+  6: SysUtils    SysUtils
+  7: Generics    Generics
+  8: Thrift      Thrift
+}
+
+
+enum Thrift4554_Enum {
+  Foo = 0,
+  Bar = 1,
+  Baz = 2,
+}
+
+struct Thrift4554_Struct {
+  1 : optional double MinValue
+  2 : optional double MaxValue
+  3 : optional bool Integer  // causes issue
+  4 : optional Thrift4554_Enum Foo
+}
+
+
+// EOF
diff --git a/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas b/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas
index 37f84bb..3860f5a 100644
--- a/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas
+++ b/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas
@@ -28,7 +28,6 @@
 uses
   Windows, SysUtils,
   Generics.Collections,
-  Thrift.Console,
   Thrift.Server,
   Thrift.Transport,
   Thrift.Transport.Pipes,
@@ -41,6 +40,7 @@
   Benchmark,  // in gen-delphi folder
   Aggr,       // in gen-delphi folder
   Multiplex.Test.Common,
+  ConsoleHelper,
   Contnrs;
 
 type
diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
index d6f93a1..4278d8f 100644
--- a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
+++ b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
@@ -27,6 +27,7 @@
   Multiplex.Client.Main in 'Multiplex.Client.Main.pas',
   Thrift in '..\..\src\Thrift.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
   Thrift.Transport.Pipes in '..\..\src\Thrift.Transport.Pipes.pas',
   Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
@@ -34,7 +35,6 @@
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas';
 
diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
index 5550036..120462b 100644
--- a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
+++ b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
@@ -24,7 +24,9 @@
 uses
   SysUtils,
   Multiplex.Server.Main in 'Multiplex.Server.Main.pas',
+  ConsoleHelper in '..\ConsoleHelper.pas',
   Thrift in '..\..\src\Thrift.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
   Thrift.Transport.Pipes in '..\..\src\Thrift.Transport.Pipes.pas',
@@ -33,7 +35,6 @@
   Thrift.Processor.Multiplex in '..\..\src\Thrift.Processor.Multiplex.pas',
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr
index 14be502..51e22a4 100644
--- a/lib/delphi/test/serializer/TestSerializer.dpr
+++ b/lib/delphi/test/serializer/TestSerializer.dpr
@@ -24,18 +24,18 @@
 uses
   Classes, Windows, SysUtils, Generics.Collections,
   Thrift in '..\..\src\Thrift.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
   Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.Serializer in '..\..\src\Thrift.Serializer.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
-  ReservedKeywords,
+  System_,
   DebugProtoTest,
   TestSerializer.Data;
 
diff --git a/lib/delphi/test/server.dpr b/lib/delphi/test/server.dpr
index d87a331..b5e48a6 100644
--- a/lib/delphi/test/server.dpr
+++ b/lib/delphi/test/server.dpr
@@ -27,6 +27,7 @@
   TestServerEvents in 'TestServerEvents.pas',
   Thrift.Test,  // in gen-delphi folder
   Thrift in '..\src\Thrift.pas',
+  Thrift.Exception in '..\src\Thrift.Exception.pas',
   Thrift.Transport in '..\src\Thrift.Transport.pas',
   Thrift.Socket in '..\src\Thrift.Socket.pas',
   Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas',
@@ -37,7 +38,6 @@
   Thrift.Processor.Multiplex in '..\src\Thrift.Processor.Multiplex.pas',
   Thrift.Collections in '..\src\Thrift.Collections.pas',
   Thrift.Server in '..\src\Thrift.Server.pas',
-  Thrift.Console in '..\src\Thrift.Console.pas',
   Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas',
   Thrift.Utils in '..\src\Thrift.Utils.pas',
   Thrift.Stream in '..\src\Thrift.Stream.pas';
diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr
index 40d025f..803d6bd 100644
--- a/lib/delphi/test/skip/skiptest_version1.dpr
+++ b/lib/delphi/test/skip/skiptest_version1.dpr
@@ -25,13 +25,13 @@
   Classes, Windows, SysUtils,
   Skiptest.One,
   Thrift in '..\..\src\Thrift.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
   Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr
index 9cb6ff6..633b247 100644
--- a/lib/delphi/test/skip/skiptest_version2.dpr
+++ b/lib/delphi/test/skip/skiptest_version2.dpr
@@ -25,13 +25,13 @@
   Classes, Windows, SysUtils,
   Skiptest.Two,
   Thrift in '..\..\src\Thrift.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
   Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
index 3a77aae..18a7c7d 100644
--- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
+++ b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
@@ -25,12 +25,12 @@
   Classes, Windows, SysUtils, Generics.Collections, TypInfo,
   Thrift in '..\..\src\Thrift.pas',
   Thrift.Transport in '..\..\src\Thrift.Transport.pas',
+  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
   Thrift.Socket in '..\..\src\Thrift.Socket.pas',
   Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Console in '..\..\src\Thrift.Console.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.Serializer in '..\..\src\Thrift.Serializer.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am
index 8867f88..06323b4 100644
--- a/lib/erl/Makefile.am
+++ b/lib/erl/Makefile.am
@@ -23,6 +23,7 @@
 		  $(THRIFT_OMIT_FILE) \
 		  ../../test/ConstantsDemo.thrift \
 		  ../../test/NameConflictTest.thrift \
+		  ../../test/DoubleConstantsTest.thrift \
 		  ../../test/ThriftTest.thrift
 
 if ERLANG_OTP16
diff --git a/lib/erl/rebar.test.config b/lib/erl/rebar.test.config
index 12515b7..2ff2afb 100644
--- a/lib/erl/rebar.test.config
+++ b/lib/erl/rebar.test.config
@@ -1,5 +1,5 @@
 {erl_opts, [{platform_define, "^R.*", otp16_or_less}, debug_info]}.
 
 {deps, [
-  {meck, "", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.2"}}}
+  {meck, "", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.9"}}}
 ]}.
diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src
index 0247494..b3b225f 100644
--- a/lib/erl/src/thrift.app.src
+++ b/lib/erl/src/thrift.app.src
@@ -22,7 +22,7 @@
   {description, "Thrift bindings"},
 
   % The version of the applicaton
-  {vsn, "0.11.0"},
+  {vsn, "1.0.0"},
 
   % All modules used by the application.
   {modules, [
diff --git a/lib/erl/test/test_rendered_double_constants.erl b/lib/erl/test/test_rendered_double_constants.erl
new file mode 100644
index 0000000..87fce81
--- /dev/null
+++ b/lib/erl/test/test_rendered_double_constants.erl
@@ -0,0 +1,68 @@
+%%
+%% 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.
+%%
+
+-module(test_rendered_double_constants).
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+-include("gen-erl/double_constants_test_constants.hrl").
+
+-define(EPSILON, 0.0000001).
+
+rendered_double_constants_test() ->
+  ?assert(abs(1.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) =< ?EPSILON),
+  ?assert(abs(-100.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) =< ?EPSILON),
+  ?assert(abs(9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) =< ?EPSILON),
+  ?assert(abs(-9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) =< ?EPSILON),
+  ?assert(abs(3.14159265359 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) =< ?EPSILON),
+  ?assert(abs(1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(abs(-1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(abs(1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(abs(9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(abs(-1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(abs(-9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)),
+  ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)).
+
+rendered_double_list_test() ->
+  ?assertEqual(12, length(?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)),
+  ?assert(abs(1.0 - lists:nth(1, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(-100.0 - lists:nth(2, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(100.0 - lists:nth(3, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(9223372036854775807.0 - lists:nth(4, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(-9223372036854775807.0 - lists:nth(5, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(3.14159265359 - lists:nth(6, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(1000000.1 - lists:nth(7, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(-1000000.1 - lists:nth(8, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(1.7e+308 - lists:nth(9, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(-1.7e+308 - lists:nth(10, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(9223372036854775816.43 - lists:nth(11, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON),
+  ?assert(abs(-9223372036854775816.43 - lists:nth(12, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON).
+
+-endif. %% TEST
\ No newline at end of file
diff --git a/lib/go/Makefile.am b/lib/go/Makefile.am
index 0d59710..0dfa5fa 100644
--- a/lib/go/Makefile.am
+++ b/lib/go/Makefile.am
@@ -31,14 +31,12 @@
 	@echo '##############################################################'
 
 check-local:
-	GOPATH=`pwd` $(GO) get golang.org/x/net/context
 	GOPATH=`pwd` $(GO) test -race ./thrift
 
 clean-local:
 	$(RM) -rf pkg
 
 all-local:
-	GOPATH=`pwd` $(GO) get golang.org/x/net/context
 	GOPATH=`pwd` $(GO) build ./thrift
 
 EXTRA_DIST = \
diff --git a/lib/go/README.md b/lib/go/README.md
index 7440474..ce6d5ed 100644
--- a/lib/go/README.md
+++ b/lib/go/README.md
@@ -24,10 +24,12 @@
 Using Thrift with Go
 ====================
 
+Thrift supports Go 1.7+
+
 In following Go conventions, we recommend you use the 'go' tool to install
 Thrift for go.
 
-    $ go get git.apache.org/thrift.git/lib/go/thrift/...
+    $ go get github.com/apache/thrift/lib/go/thrift/...
 
 Will retrieve and install the most recent version of the package.
 
diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am
index 842f2de..78d4681 100644
--- a/lib/go/test/Makefile.am
+++ b/lib/go/test/Makefile.am
@@ -17,10 +17,6 @@
 # under the License.
 #
 
-if GOVERSION_LT_17
-COMPILER_EXTRAFLAG=",legacy_context"
-endif
-
 THRIFTARGS = -out gopath/src/ --gen go:thrift_import=thrift$(COMPILER_EXTRAFLAG)
 THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift
 
@@ -31,11 +27,13 @@
 				MultiplexedProtocolTest.thrift \
 				OnewayTest.thrift \
 				OptionalFieldsTest.thrift \
+				RequiredFieldTest.thrift \
 				ServicesTest.thrift \
 				GoTagTest.thrift \
 				TypedefFieldTest.thrift \
 				RefAnnotationFieldsTest.thrift \
 				UnionDefaultValueTest.thrift \
+				UnionBinaryTest.thrift \
 				ErrorTest.thrift \
 				NamesTest.thrift \
 				InitialismsTest.thrift \
@@ -49,17 +47,18 @@
 	$(THRIFT) $(THRIFTARGS) MultiplexedProtocolTest.thrift
 	$(THRIFT) $(THRIFTARGS) OnewayTest.thrift
 	$(THRIFT) $(THRIFTARGS) OptionalFieldsTest.thrift
+	$(THRIFT) $(THRIFTARGS) RequiredFieldTest.thrift
 	$(THRIFT) $(THRIFTARGS) ServicesTest.thrift
 	$(THRIFT) $(THRIFTARGS) GoTagTest.thrift
 	$(THRIFT) $(THRIFTARGS) TypedefFieldTest.thrift
 	$(THRIFT) $(THRIFTARGS) RefAnnotationFieldsTest.thrift
 	$(THRIFT) $(THRIFTARGS) UnionDefaultValueTest.thrift
+	$(THRIFT) $(THRIFTARGS) UnionBinaryTest.thrift
 	$(THRIFT) $(THRIFTARGS) ErrorTest.thrift
 	$(THRIFT) $(THRIFTARGS) NamesTest.thrift
 	$(THRIFT) $(THRIFTARGS) InitialismsTest.thrift
 	$(THRIFT) $(THRIFTARGS),read_write_private DontExportRWTest.thrift
 	$(THRIFT) $(THRIFTARGS),ignore_initialisms IgnoreInitialismsTest.thrift
-	GOPATH=`pwd`/gopath $(GO) get golang.org/x/net/context
 	GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true
 	sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true
 	GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock
@@ -79,7 +78,8 @@
 				namestest \
 				initialismstest \
 				dontexportrwtest \
-				ignoreinitialismstest
+				ignoreinitialismstest \
+				unionbinarytest
 	GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest
 
 clean-local:
@@ -98,8 +98,10 @@
 	NamespacedTest.thrift \
 	OnewayTest.thrift \
 	OptionalFieldsTest.thrift \
+	RequiredFieldTest.thrift \
 	RefAnnotationFieldsTest.thrift \
 	UnionDefaultValueTest.thrift \
+	UnionBinaryTest.thrift \
 	ServicesTest.thrift \
 	TypedefFieldTest.thrift \
 	ErrorTest.thrift \
diff --git a/lib/go/test/RequiredFieldTest.thrift b/lib/go/test/RequiredFieldTest.thrift
new file mode 100644
index 0000000..4a2dcae
--- /dev/null
+++ b/lib/go/test/RequiredFieldTest.thrift
@@ -0,0 +1,7 @@
+struct RequiredField {
+  1: required string name
+}
+
+struct OtherThing {
+  1: required i16 value
+}
diff --git a/lib/go/test/UnionBinaryTest.thrift b/lib/go/test/UnionBinaryTest.thrift
new file mode 100644
index 0000000..f77112b
--- /dev/null
+++ b/lib/go/test/UnionBinaryTest.thrift
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+# See https://issues.apache.org/jira/browse/THRIFT-4573
+union Sample {
+  1: map<string, string> u1,
+  2: binary u2,
+  3: list<string> u3
+}
diff --git a/lib/go/test/dontexportrwtest/compile_test.go b/lib/go/test/dontexportrwtest/compile_test.go
index 2b877e3..cf6763e 100644
--- a/lib/go/test/dontexportrwtest/compile_test.go
+++ b/lib/go/test/dontexportrwtest/compile_test.go
@@ -20,7 +20,6 @@
 package dontexportrwtest
 
 import (
-	"fmt"
 	"testing"
 )
 
@@ -29,10 +28,10 @@
 func TestReadWriteMethodsArePrivate(t *testing.T) {
 	// This will only compile if read/write methods exist
 	s := NewTestStruct()
-	fmt.Sprintf("%v", s.read)
-	fmt.Sprintf("%v", s.write)
+	_ = s.read
+	_ = s.write
 
 	is := NewInnerStruct()
-	fmt.Sprintf("%v", is.read)
-	fmt.Sprintf("%v", is.write)
+	_ = is.read
+	_ = is.write
 }
diff --git a/lib/go/test/tests/client_error_test.go b/lib/go/test/tests/client_error_test.go
index 4a8ef13..fdec4ea 100644
--- a/lib/go/test/tests/client_error_test.go
+++ b/lib/go/test/tests/client_error_test.go
@@ -20,6 +20,7 @@
 package tests
 
 import (
+	"context"
 	"errors"
 	"errortest"
 	"testing"
@@ -212,7 +213,7 @@
 	if failAt == 25 {
 		err = failWith
 	}
-	last = protocol.EXPECT().Flush().Return(err).After(last)
+	last = protocol.EXPECT().Flush(context.Background()).Return(err).After(last)
 	if failAt == 25 {
 		return true
 	}
@@ -414,6 +415,7 @@
 		client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
 		_, retErr := client.TestStruct(defaultCtx, thing)
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 		err2, ok := retErr.(thrift.TTransportException)
 		if !ok {
 			t.Fatal("Expected a TTrasportException")
@@ -446,6 +448,7 @@
 		client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
 		_, retErr := client.TestStruct(defaultCtx, thing)
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 		err2, ok := retErr.(thrift.TTransportException)
 		if !ok {
 			t.Fatal("Expected a TTrasportException")
@@ -477,6 +480,7 @@
 		client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
 		_, retErr := client.TestStruct(defaultCtx, thing)
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 		err2, ok := retErr.(thrift.TProtocolException)
 		if !ok {
 			t.Fatal("Expected a TProtocolException")
@@ -508,6 +512,7 @@
 		client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
 		_, retErr := client.TestStruct(defaultCtx, thing)
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 		err2, ok := retErr.(thrift.TProtocolException)
 		if !ok {
 			t.Fatal("Expected a TProtocolException")
@@ -532,7 +537,7 @@
 	last = protocol.EXPECT().WriteFieldStop().After(last)
 	last = protocol.EXPECT().WriteStructEnd().After(last)
 	last = protocol.EXPECT().WriteMessageEnd().After(last)
-	last = protocol.EXPECT().Flush().After(last)
+	last = protocol.EXPECT().Flush(context.Background()).After(last)
 
 	// Reading the exception, might fail.
 	if failAt == 0 {
@@ -628,6 +633,7 @@
 		client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
 		_, retErr := client.TestString(defaultCtx, "test")
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 
 		if !willComplete {
 			err2, ok := retErr.(thrift.TTransportException)
@@ -663,6 +669,7 @@
 		client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
 		_, retErr := client.TestString(defaultCtx, "test")
 		mockCtrl.Finish()
+		mockCtrl = gomock.NewController(t)
 
 		if !willComplete {
 			err2, ok := retErr.(thrift.TTransportException)
@@ -698,7 +705,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.REPLY, int32(2), nil),
 	)
 
@@ -729,7 +736,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.REPLY, int32(2), nil),
 	)
 
@@ -758,7 +765,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("unknown", thrift.REPLY, int32(1), nil),
 	)
 
@@ -789,7 +796,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("unknown", thrift.REPLY, int32(1), nil),
 	)
 
@@ -818,7 +825,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil),
 	)
 
@@ -849,7 +856,7 @@
 		protocol.EXPECT().WriteFieldStop(),
 		protocol.EXPECT().WriteStructEnd(),
 		protocol.EXPECT().WriteMessageEnd(),
-		protocol.EXPECT().Flush(),
+		protocol.EXPECT().Flush(context.Background()),
 		protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil),
 	)
 
diff --git a/test/go/src/bin/testclient/go17.go b/lib/go/test/tests/context.go
similarity index 93%
rename from test/go/src/bin/testclient/go17.go
rename to lib/go/test/tests/context.go
index a6003a9..a93a82b 100644
--- a/test/go/src/bin/testclient/go17.go
+++ b/lib/go/test/tests/context.go
@@ -1,5 +1,3 @@
-// +build go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,8 +17,10 @@
  * under the License.
  */
 
-package main
+package tests
 
-import "context"
+import (
+	"context"
+)
 
 var defaultCtx = context.Background()
diff --git a/lib/go/test/tests/go17.go b/lib/go/test/tests/go17.go
deleted file mode 100644
index dc3c9d5..0000000
--- a/lib/go/test/tests/go17.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package tests
-
-import (
-	"context"
-	"fmt"
-)
-
-var defaultCtx = context.Background()
-
-type FirstImpl struct{}
-
-func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) {
-	return 1, nil
-}
-
-type SecondImpl struct{}
-
-func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) {
-	return 2, nil
-}
-
-type impl struct{}
-
-func (i *impl) Hi(ctx context.Context, in int64, s string) (err error)        { fmt.Println("Hi!"); return }
-func (i *impl) Emptyfunc(ctx context.Context) (err error)                     { return }
-func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil }
diff --git a/lib/go/test/tests/multiplexed_protocol_test.go b/lib/go/test/tests/multiplexed_protocol_test.go
index 0b5896b..61ac628 100644
--- a/lib/go/test/tests/multiplexed_protocol_test.go
+++ b/lib/go/test/tests/multiplexed_protocol_test.go
@@ -20,6 +20,7 @@
 package tests
 
 import (
+	"context"
 	"multiplexedprotocoltest"
 	"net"
 	"testing"
@@ -36,6 +37,18 @@
 	}
 }
 
+type FirstImpl struct{}
+
+func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) {
+	return 1, nil
+}
+
+type SecondImpl struct{}
+
+func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) {
+	return 2, nil
+}
+
 func createTransport(addr net.Addr) (thrift.TTransport, error) {
 	socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
 	transport := thrift.NewTFramedTransport(socket)
diff --git a/lib/go/test/tests/one_way_test.go b/lib/go/test/tests/one_way_test.go
index 8abd671..48d0bbe 100644
--- a/lib/go/test/tests/one_way_test.go
+++ b/lib/go/test/tests/one_way_test.go
@@ -20,6 +20,8 @@
 package tests
 
 import (
+	"context"
+	"fmt"
 	"net"
 	"onewaytest"
 	"testing"
@@ -36,6 +38,12 @@
 	}
 }
 
+type impl struct{}
+
+func (i *impl) Hi(ctx context.Context, in int64, s string) (err error)        { fmt.Println("Hi!"); return }
+func (i *impl) Emptyfunc(ctx context.Context) (err error)                     { return }
+func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil }
+
 const TIMEOUT = time.Second
 
 var addr net.Addr
diff --git a/lib/go/test/tests/pre_go17.go b/lib/go/test/tests/pre_go17.go
deleted file mode 100644
index 8ab4331..0000000
--- a/lib/go/test/tests/pre_go17.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package tests
-
-import (
-	"fmt"
-
-	"golang.org/x/net/context"
-)
-
-var defaultCtx = context.Background()
-
-type FirstImpl struct{}
-
-func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) {
-	return 1, nil
-}
-
-type SecondImpl struct{}
-
-func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) {
-	return 2, nil
-}
-
-type impl struct{}
-
-func (i *impl) Hi(ctx context.Context, in int64, s string) (err error)        { fmt.Println("Hi!"); return }
-func (i *impl) Emptyfunc(ctx context.Context) (err error)                     { return }
-func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil }
diff --git a/lib/go/test/tests/protocol_mock.go b/lib/go/test/tests/protocol_mock.go
index 8476c86..51d7a02 100644
--- a/lib/go/test/tests/protocol_mock.go
+++ b/lib/go/test/tests/protocol_mock.go
@@ -23,6 +23,7 @@
 package tests
 
 import (
+	"context"
 	thrift "thrift"
 
 	gomock "github.com/golang/mock/gomock"
@@ -49,13 +50,13 @@
 	return _m.recorder
 }
 
-func (_m *MockTProtocol) Flush() error {
+func (_m *MockTProtocol) Flush(ctx context.Context) error {
 	ret := _m.ctrl.Call(_m, "Flush")
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
-func (_mr *_MockTProtocolRecorder) Flush() *gomock.Call {
+func (_mr *_MockTProtocolRecorder) Flush(ctx context.Context) *gomock.Call {
 	return _mr.mock.ctrl.RecordCall(_mr.mock, "Flush")
 }
 
diff --git a/lib/go/test/tests/required_fields_test.go b/lib/go/test/tests/required_fields_test.go
index 2053712..3fa414a 100644
--- a/lib/go/test/tests/required_fields_test.go
+++ b/lib/go/test/tests/required_fields_test.go
@@ -20,12 +20,45 @@
 package tests
 
 import (
+	"context"
 	"github.com/golang/mock/gomock"
 	"optionalfieldstest"
+	"requiredfieldtest"
 	"testing"
 	"thrift"
 )
 
+func TestRequiredField_SucecssWhenSet(t *testing.T) {
+	// create a new RequiredField instance with the required field set
+	source := &requiredfieldtest.RequiredField{Name: "this is a test"}
+	sourceData, err := thrift.NewTSerializer().Write(context.Background(), source)
+	if err != nil {
+		t.Fatalf("failed to serialize %T: %v", source, err)
+	}
+
+	d := thrift.NewTDeserializer()
+	err = d.Read(&requiredfieldtest.RequiredField{}, sourceData)
+	if err != nil {
+		t.Fatalf("Did not expect an error when trying to deserialize the requiredfieldtest.RequiredField: %v", err)
+	}
+}
+
+func TestRequiredField_ErrorWhenMissing(t *testing.T) {
+	// create a new OtherThing instance, without setting the required field
+	source := &requiredfieldtest.OtherThing{}
+	sourceData, err := thrift.NewTSerializer().Write(context.Background(), source)
+	if err != nil {
+		t.Fatalf("failed to serialize %T: %v", source, err)
+	}
+
+	// attempt to deserialize into a different type (which should fail)
+	d := thrift.NewTDeserializer()
+	err = d.Read(&requiredfieldtest.RequiredField{}, sourceData)
+	if err == nil {
+		t.Fatal("Expected an error when trying to deserialize an object which is missing a required field")
+	}
+}
+
 func TestStructReadRequiredFields(t *testing.T) {
 	mockCtrl := gomock.NewController(t)
 	protocol := NewMockTProtocol(mockCtrl)
@@ -40,6 +73,7 @@
 
 	err := testStruct.Read(protocol)
 	mockCtrl.Finish()
+	mockCtrl = gomock.NewController(t)
 	if err == nil {
 		t.Fatal("Expected read to fail")
 	}
@@ -63,6 +97,7 @@
 
 	err = testStruct.Read(protocol)
 	mockCtrl.Finish()
+	mockCtrl = gomock.NewController(t)
 	if err == nil {
 		t.Fatal("Expected read to fail")
 	}
diff --git a/lib/go/test/tests/thrifttest_handler.go b/lib/go/test/tests/thrifttest_handler.go
index 6542fac..31b9ee2 100644
--- a/lib/go/test/tests/thrifttest_handler.go
+++ b/lib/go/test/tests/thrifttest_handler.go
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -22,12 +20,11 @@
 package tests
 
 import (
+	"context"
 	"errors"
 	"thrift"
 	"thrifttest"
 	"time"
-
-	"golang.org/x/net/context"
 )
 
 type SecondServiceHandler struct {
diff --git a/lib/go/test/tests/thrifttest_handler_go17.go b/lib/go/test/tests/thrifttest_handler_go17.go
deleted file mode 100644
index e022a3d..0000000
--- a/lib/go/test/tests/thrifttest_handler_go17.go
+++ /dev/null
@@ -1,212 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package tests
-
-import (
-	"context"
-	"errors"
-	"thrift"
-	"thrifttest"
-	"time"
-)
-
-type SecondServiceHandler struct {
-}
-
-func NewSecondServiceHandler() *SecondServiceHandler {
-	return &SecondServiceHandler{}
-}
-
-func (p *SecondServiceHandler) BlahBlah(ctx context.Context) (err error) {
-	return nil
-}
-
-func (p *SecondServiceHandler) SecondtestString(ctx context.Context, thing string) (r string, err error) {
-	return thing, nil
-}
-
-type ThriftTestHandler struct {
-}
-
-func NewThriftTestHandler() *ThriftTestHandler {
-	return &ThriftTestHandler{}
-}
-
-func (p *ThriftTestHandler) TestVoid(ctx context.Context) (err error) {
-	return nil
-}
-
-func (p *ThriftTestHandler) TestString(ctx context.Context, thing string) (r string, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestStruct(ctx context.Context, thing *thrifttest.Xtruct) (r *thrifttest.Xtruct, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestNest(ctx context.Context, thing *thrifttest.Xtruct2) (r *thrifttest.Xtruct2, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestEnum(ctx context.Context, thing thrifttest.Numberz) (r thrifttest.Numberz, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestTypedef(ctx context.Context, thing thrifttest.UserId) (r thrifttest.UserId, err error) {
-	return thing, nil
-}
-
-func (p *ThriftTestHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) {
-	r = make(map[int32]map[int32]int32)
-	pos := make(map[int32]int32)
-	neg := make(map[int32]int32)
-
-	for i := int32(1); i < 5; i++ {
-		pos[i] = i
-		neg[-i] = -i
-	}
-	r[4] = pos
-	r[-4] = neg
-
-	return r, nil
-}
-
-func (p *ThriftTestHandler) TestInsanity(ctx context.Context, argument *thrifttest.Insanity) (r map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity, err error) {
-	hello := thrifttest.NewXtruct()
-	hello.StringThing = "Hello2"
-	hello.ByteThing = 2
-	hello.I32Thing = 2
-	hello.I64Thing = 2
-
-	goodbye := thrifttest.NewXtruct()
-	goodbye.StringThing = "Goodbye4"
-	goodbye.ByteThing = 4
-	goodbye.I32Thing = 4
-	goodbye.I64Thing = 4
-
-	crazy := thrifttest.NewInsanity()
-	crazy.UserMap = make(map[thrifttest.Numberz]thrifttest.UserId)
-	crazy.UserMap[thrifttest.Numberz_EIGHT] = 8
-	crazy.UserMap[thrifttest.Numberz_FIVE] = 5
-	crazy.Xtructs = []*thrifttest.Xtruct{goodbye, hello}
-
-	first_map := make(map[thrifttest.Numberz]*thrifttest.Insanity)
-	second_map := make(map[thrifttest.Numberz]*thrifttest.Insanity)
-
-	first_map[thrifttest.Numberz_TWO] = crazy
-	first_map[thrifttest.Numberz_THREE] = crazy
-
-	looney := thrifttest.NewInsanity()
-	second_map[thrifttest.Numberz_SIX] = looney
-
-	var insane = make(map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity)
-	insane[1] = first_map
-	insane[2] = second_map
-
-	return insane, nil
-}
-
-func (p *ThriftTestHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 thrifttest.Numberz, arg5 thrifttest.UserId) (r *thrifttest.Xtruct, err error) {
-	r = thrifttest.NewXtruct()
-	r.StringThing = "Hello2"
-	r.ByteThing = arg0
-	r.I32Thing = arg1
-	r.I64Thing = arg2
-	return r, nil
-}
-
-func (p *ThriftTestHandler) TestException(ctx context.Context, arg string) (err error) {
-	if arg == "Xception" {
-		x := thrifttest.NewXception()
-		x.ErrorCode = 1001
-		x.Message = arg
-		return x
-	} else if arg == "TException" {
-		return thrift.TException(errors.New(arg))
-	} else {
-		return nil
-	}
-}
-
-func (p *ThriftTestHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *thrifttest.Xtruct, err error) {
-	if arg0 == "Xception" {
-		x := thrifttest.NewXception()
-		x.ErrorCode = 1001
-		x.Message = "This is an Xception"
-		return nil, x
-	} else if arg0 == "Xception2" {
-		x2 := thrifttest.NewXception2()
-		x2.ErrorCode = 2002
-		x2.StructThing = thrifttest.NewXtruct()
-		x2.StructThing.StringThing = "This is an Xception2"
-		return nil, x2
-	}
-
-	res := thrifttest.NewXtruct()
-	res.StringThing = arg1
-	return res, nil
-}
-
-func (p *ThriftTestHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) {
-	time.Sleep(time.Second * time.Duration(secondsToSleep))
-	return nil
-}
diff --git a/lib/go/thrift/common_test_pre_go17.go b/lib/go/test/tests/union_binary_test.go
similarity index 70%
copy from lib/go/thrift/common_test_pre_go17.go
copy to lib/go/test/tests/union_binary_test.go
index e6d0c4d..bdae2cb 100644
--- a/lib/go/thrift/common_test_pre_go17.go
+++ b/lib/go/test/tests/union_binary_test.go
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,14 +17,20 @@
  * under the License.
  */
 
-package thrift
+package tests
 
-import "golang.org/x/net/context"
+import (
+	"testing"
+	"unionbinarytest"
+)
 
-type mockProcessor struct {
-	ProcessFunc func(in, out TProtocol) (bool, TException)
-}
 
-func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	return m.ProcessFunc(in, out)
+// See https://issues.apache.org/jira/browse/THRIFT-4573
+func TestUnionBinary(t *testing.T) {
+	s := unionbinarytest.NewSample()
+	s.U1 = map[string]string{}
+	s.U2 = []byte{}
+	if n := s.CountSetFieldsSample(); n != 2 {
+		t.Errorf("Expected 2 set fields, got %d!", n)
+	}
 }
diff --git a/lib/go/thrift/application_exception_test.go b/lib/go/thrift/application_exception_test.go
index b2687a6..7743357 100644
--- a/lib/go/thrift/application_exception_test.go
+++ b/lib/go/thrift/application_exception_test.go
@@ -29,13 +29,13 @@
 		t.Fatalf("Expected empty string for exception but found '%s'", exc.Error())
 	}
 	if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION {
-		t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId())
+		t.Fatalf("Expected type UNKNOWN for exception but found '%v'", exc.TypeId())
 	}
 	exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method")
 	if exc.Error() != "junk_method" {
 		t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.Error())
 	}
 	if exc.TypeId() != WRONG_METHOD_NAME {
-		t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId())
+		t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%v'", exc.TypeId())
 	}
 }
diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go
index 690d341..1f90bf4 100644
--- a/lib/go/thrift/binary_protocol.go
+++ b/lib/go/thrift/binary_protocol.go
@@ -21,6 +21,7 @@
 
 import (
 	"bytes"
+	"context"
 	"encoding/binary"
 	"errors"
 	"fmt"
@@ -447,9 +448,6 @@
 	if size < 0 {
 		return nil, invalidDataLength
 	}
-	if uint64(size) > p.trans.RemainingBytes() {
-		return nil, invalidDataLength
-	}
 
 	isize := int(size)
 	buf := make([]byte, isize)
@@ -457,8 +455,8 @@
 	return buf, NewTProtocolException(err)
 }
 
-func (p *TBinaryProtocol) Flush() (err error) {
-	return NewTProtocolException(p.trans.Flush())
+func (p *TBinaryProtocol) Flush(ctx context.Context) (err error) {
+	return NewTProtocolException(p.trans.Flush(ctx))
 }
 
 func (p *TBinaryProtocol) Skip(fieldType TType) (err error) {
@@ -480,9 +478,6 @@
 	if size < 0 {
 		return "", nil
 	}
-	if uint64(size) > p.trans.RemainingBytes() {
-		return "", invalidDataLength
-	}
 
 	var (
 		buf bytes.Buffer
diff --git a/lib/go/thrift/buffered_transport.go b/lib/go/thrift/buffered_transport.go
index b754f92..9670206 100644
--- a/lib/go/thrift/buffered_transport.go
+++ b/lib/go/thrift/buffered_transport.go
@@ -21,6 +21,7 @@
 
 import (
 	"bufio"
+	"context"
 )
 
 type TBufferedTransportFactory struct {
@@ -78,12 +79,12 @@
 	return n, err
 }
 
-func (p *TBufferedTransport) Flush() error {
+func (p *TBufferedTransport) Flush(ctx context.Context) error {
 	if err := p.ReadWriter.Flush(); err != nil {
 		p.ReadWriter.Writer.Reset(p.tp)
 		return err
 	}
-	return p.tp.Flush()
+	return p.tp.Flush(ctx)
 }
 
 func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) {
diff --git a/lib/go/thrift/client.go b/lib/go/thrift/client.go
index 8bdb53d..28791cc 100644
--- a/lib/go/thrift/client.go
+++ b/lib/go/thrift/client.go
@@ -1,6 +1,13 @@
 package thrift
 
-import "fmt"
+import (
+	"context"
+	"fmt"
+)
+
+type TClient interface {
+	Call(ctx context.Context, method string, args, result TStruct) error
+}
 
 type TStandardClient struct {
 	seqId        int32
@@ -16,7 +23,7 @@
 	}
 }
 
-func (p *TStandardClient) Send(oprot TProtocol, seqId int32, method string, args TStruct) error {
+func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error {
 	if err := oprot.WriteMessageBegin(method, CALL, seqId); err != nil {
 		return err
 	}
@@ -26,7 +33,7 @@
 	if err := oprot.WriteMessageEnd(); err != nil {
 		return err
 	}
-	return oprot.Flush()
+	return oprot.Flush(ctx)
 }
 
 func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, result TStruct) error {
@@ -61,11 +68,11 @@
 	return iprot.ReadMessageEnd()
 }
 
-func (p *TStandardClient) call(method string, args, result TStruct) error {
+func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
 	p.seqId++
 	seqId := p.seqId
 
-	if err := p.Send(p.oprot, seqId, method, args); err != nil {
+	if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil {
 		return err
 	}
 
diff --git a/lib/go/thrift/client_go17.go b/lib/go/thrift/client_go17.go
deleted file mode 100644
index 15c1c52..0000000
--- a/lib/go/thrift/client_go17.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build go1.7
-
-package thrift
-
-import "context"
-
-type TClient interface {
-	Call(ctx context.Context, method string, args, result TStruct) error
-}
-
-func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
-	return p.call(method, args, result)
-}
diff --git a/lib/go/thrift/client_pre_go17.go b/lib/go/thrift/client_pre_go17.go
deleted file mode 100644
index d2e99ef..0000000
--- a/lib/go/thrift/client_pre_go17.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !go1.7
-
-package thrift
-
-import "golang.org/x/net/context"
-
-type TClient interface {
-	Call(ctx context.Context, method string, args, result TStruct) error
-}
-
-func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
-	return p.call(method, args, result)
-}
diff --git a/lib/go/thrift/common_test_go17.go b/lib/go/thrift/common_test.go
similarity index 97%
rename from lib/go/thrift/common_test_go17.go
rename to lib/go/thrift/common_test.go
index 2c729a2..93597ff 100644
--- a/lib/go/thrift/common_test_go17.go
+++ b/lib/go/thrift/common_test.go
@@ -1,5 +1,3 @@
-// +build go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go
index 0bc5fdd..1900d50 100644
--- a/lib/go/thrift/compact_protocol.go
+++ b/lib/go/thrift/compact_protocol.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"encoding/binary"
 	"fmt"
 	"io"
@@ -561,9 +562,6 @@
 	if length < 0 {
 		return "", invalidDataLength
 	}
-	if uint64(length) > p.trans.RemainingBytes() {
-		return "", invalidDataLength
-	}
 
 	if length == 0 {
 		return "", nil
@@ -590,17 +588,14 @@
 	if length < 0 {
 		return nil, invalidDataLength
 	}
-	if uint64(length) > p.trans.RemainingBytes() {
-		return nil, invalidDataLength
-	}
 
 	buf := make([]byte, length)
 	_, e = io.ReadFull(p.trans, buf)
 	return buf, NewTProtocolException(e)
 }
 
-func (p *TCompactProtocol) Flush() (err error) {
-	return NewTProtocolException(p.trans.Flush())
+func (p *TCompactProtocol) Flush(ctx context.Context) (err error) {
+	return NewTProtocolException(p.trans.Flush(ctx))
 }
 
 func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
@@ -806,7 +801,7 @@
 	case COMPACT_STRUCT:
 		return STRUCT, nil
 	}
-	return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f))
+	return STOP, TException(fmt.Errorf("don't know what type: %v", t&0x0f))
 }
 
 // Given a TType value, find the appropriate TCompactProtocol.Types constant.
diff --git a/lib/go/thrift/compact_protocol_test.go b/lib/go/thrift/compact_protocol_test.go
index f940b4e..65f77f2 100644
--- a/lib/go/thrift/compact_protocol_test.go
+++ b/lib/go/thrift/compact_protocol_test.go
@@ -26,11 +26,18 @@
 
 func TestReadWriteCompactProtocol(t *testing.T) {
 	ReadWriteProtocolTest(t, NewTCompactProtocolFactory())
+
 	transports := []TTransport{
 		NewTMemoryBuffer(),
 		NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))),
 		NewTFramedTransport(NewTMemoryBuffer()),
 	}
+
+	zlib0, _ := NewTZlibTransport(NewTMemoryBuffer(), 0)
+	zlib6, _ := NewTZlibTransport(NewTMemoryBuffer(), 6)
+	zlib9, _ := NewTZlibTransport(NewTFramedTransport(NewTMemoryBuffer()), 9)
+	transports = append(transports, zlib0, zlib6, zlib9)
+
 	for _, trans := range transports {
 		p := NewTCompactProtocol(trans)
 		ReadWriteBool(t, p, trans)
diff --git a/lib/go/thrift/go17.go b/lib/go/thrift/context.go
similarity index 97%
rename from lib/go/thrift/go17.go
rename to lib/go/thrift/context.go
index e3b21c4..d15c1bc 100644
--- a/lib/go/thrift/go17.go
+++ b/lib/go/thrift/context.go
@@ -1,5 +1,3 @@
-// +build go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
diff --git a/lib/go/thrift/debug_protocol.go b/lib/go/thrift/debug_protocol.go
index d37252c..57943e0 100644
--- a/lib/go/thrift/debug_protocol.go
+++ b/lib/go/thrift/debug_protocol.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"log"
 )
 
@@ -258,8 +259,8 @@
 	log.Printf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err)
 	return
 }
-func (tdp *TDebugProtocol) Flush() (err error) {
-	err = tdp.Delegate.Flush()
+func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) {
+	err = tdp.Delegate.Flush(ctx)
 	log.Printf("%sFlush() (err=%#v)", tdp.LogPrefix, err)
 	return
 }
diff --git a/lib/go/thrift/framed_transport.go b/lib/go/thrift/framed_transport.go
index 60b1249..81fa65a 100644
--- a/lib/go/thrift/framed_transport.go
+++ b/lib/go/thrift/framed_transport.go
@@ -22,6 +22,7 @@
 import (
 	"bufio"
 	"bytes"
+	"context"
 	"encoding/binary"
 	"fmt"
 	"io"
@@ -135,7 +136,7 @@
 	return p.buf.WriteString(s)
 }
 
-func (p *TFramedTransport) Flush() error {
+func (p *TFramedTransport) Flush(ctx context.Context) error {
 	size := p.buf.Len()
 	buf := p.buffer[:4]
 	binary.BigEndian.PutUint32(buf, uint32(size))
@@ -151,7 +152,7 @@
 			return NewTTransportExceptionFromError(err)
 		}
 	}
-	err = p.transport.Flush()
+	err = p.transport.Flush(ctx)
 	return NewTTransportExceptionFromError(err)
 }
 
diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go
index 33f2aa4..5c82bf5 100644
--- a/lib/go/thrift/http_client.go
+++ b/lib/go/thrift/http_client.go
@@ -21,6 +21,7 @@
 
 import (
 	"bytes"
+	"context"
 	"io"
 	"io/ioutil"
 	"net/http"
@@ -181,7 +182,7 @@
 	return p.requestBuffer.WriteString(s)
 }
 
-func (p *THttpClient) Flush() error {
+func (p *THttpClient) Flush(ctx context.Context) error {
 	// Close any previous response body to avoid leaking connections.
 	p.closeResponse()
 
@@ -190,6 +191,9 @@
 		return NewTTransportExceptionFromError(err)
 	}
 	req.Header = p.header
+	if ctx != nil {
+		req = req.WithContext(ctx)
+	}
 	response, err := p.client.Do(req)
 	if err != nil {
 		return NewTTransportExceptionFromError(err)
diff --git a/lib/go/thrift/http_transport.go b/lib/go/thrift/http_transport.go
index 601855b..66f0f38 100644
--- a/lib/go/thrift/http_transport.go
+++ b/lib/go/thrift/http_transport.go
@@ -26,6 +26,18 @@
 	"strings"
 )
 
+// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function
+func NewThriftHandlerFunc(processor TProcessor,
+	inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) {
+
+	return gz(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Add("Content-Type", "application/x-thrift")
+
+		transport := NewStreamTransport(r.Body, w)
+		processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport))
+	})
+}
+
 // gz transparently compresses the HTTP response if the client supports it.
 func gz(handler http.HandlerFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
diff --git a/lib/go/thrift/http_transport_go17.go b/lib/go/thrift/http_transport_go17.go
deleted file mode 100644
index 1313ac2..0000000
--- a/lib/go/thrift/http_transport_go17.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import (
-	"net/http"
-)
-
-// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function
-func NewThriftHandlerFunc(processor TProcessor,
-	inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) {
-
-	return gz(func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Add("Content-Type", "application/x-thrift")
-
-		transport := NewStreamTransport(r.Body, w)
-		processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport))
-	})
-}
diff --git a/lib/go/thrift/http_transport_pre_go17.go b/lib/go/thrift/http_transport_pre_go17.go
deleted file mode 100644
index 13aa1c1..0000000
--- a/lib/go/thrift/http_transport_pre_go17.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import (
-	"net/http"
-
-	"golang.org/x/net/context"
-)
-
-// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function
-func NewThriftHandlerFunc(processor TProcessor,
-	inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) {
-
-	return gz(func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Add("Content-Type", "application/x-thrift")
-
-		transport := NewStreamTransport(r.Body, w)
-		processor.Process(context.Background(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport))
-	})
-}
diff --git a/lib/go/thrift/iostream_transport.go b/lib/go/thrift/iostream_transport.go
index b18be81..fea93bc 100644
--- a/lib/go/thrift/iostream_transport.go
+++ b/lib/go/thrift/iostream_transport.go
@@ -21,6 +21,7 @@
 
 import (
 	"bufio"
+	"context"
 	"io"
 )
 
@@ -138,7 +139,7 @@
 }
 
 // Flushes the underlying output stream if not null.
-func (p *StreamTransport) Flush() error {
+func (p *StreamTransport) Flush(ctx context.Context) error {
 	if p.Writer == nil {
 		return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream")
 	}
diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go
index 442fa91..7be685d 100644
--- a/lib/go/thrift/json_protocol.go
+++ b/lib/go/thrift/json_protocol.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"encoding/base64"
 	"fmt"
 )
@@ -438,10 +439,10 @@
 	return v, p.ParsePostValue()
 }
 
-func (p *TJSONProtocol) Flush() (err error) {
+func (p *TJSONProtocol) Flush(ctx context.Context) (err error) {
 	err = p.writer.Flush()
 	if err == nil {
-		err = p.trans.Flush()
+		err = p.trans.Flush(ctx)
 	}
 	return NewTProtocolException(err)
 }
diff --git a/lib/go/thrift/json_protocol_test.go b/lib/go/thrift/json_protocol_test.go
index 7104ce3..59c4d64 100644
--- a/lib/go/thrift/json_protocol_test.go
+++ b/lib/go/thrift/json_protocol_test.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
@@ -36,7 +37,7 @@
 		if e := p.WriteBool(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -68,7 +69,7 @@
 		} else {
 			trans.Write([]byte{'0'}) // not JSON_FALSE
 		}
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadBool()
 		if e != nil {
@@ -94,7 +95,7 @@
 		if e := p.WriteByte(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -116,7 +117,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadByte()
 		if e != nil {
@@ -141,7 +142,7 @@
 		if e := p.WriteI16(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -163,7 +164,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI16()
 		if e != nil {
@@ -188,7 +189,7 @@
 		if e := p.WriteI32(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -210,7 +211,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI32()
 		if e != nil {
@@ -235,7 +236,7 @@
 		if e := p.WriteI64(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -257,7 +258,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTJSONProtocol(trans)
 		trans.WriteString(strconv.FormatInt(value, 10))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI64()
 		if e != nil {
@@ -282,7 +283,7 @@
 		if e := p.WriteDouble(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -319,7 +320,7 @@
 		p := NewTJSONProtocol(trans)
 		n := NewNumericFromDouble(value)
 		trans.WriteString(n.String())
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadDouble()
 		if e != nil {
@@ -358,7 +359,7 @@
 		if e := p.WriteString(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -380,7 +381,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTJSONProtocol(trans)
 		trans.WriteString(jsonQuote(value))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadString()
 		if e != nil {
@@ -409,7 +410,7 @@
 	if e := p.WriteBinary(value); e != nil {
 		t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 	}
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 	}
 	s := trans.String()
@@ -441,7 +442,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTJSONProtocol(trans)
 	trans.WriteString(jsonQuote(b64String))
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	v, e := p.ReadBinary()
 	if e != nil {
@@ -474,7 +475,7 @@
 		}
 	}
 	p.WriteListEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
@@ -528,7 +529,7 @@
 		}
 	}
 	p.WriteSetEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
@@ -585,12 +586,12 @@
 		}
 	}
 	p.WriteMapEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
 	if str[0] != '[' || str[len(str)-1] != ']' {
-		t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES)
+		t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES)
 	}
 	expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin()
 	if err != nil {
diff --git a/lib/go/thrift/memory_buffer.go b/lib/go/thrift/memory_buffer.go
index 97a4edf..5936d27 100644
--- a/lib/go/thrift/memory_buffer.go
+++ b/lib/go/thrift/memory_buffer.go
@@ -21,6 +21,7 @@
 
 import (
 	"bytes"
+	"context"
 )
 
 // Memory buffer-based implementation of the TTransport interface.
@@ -70,7 +71,7 @@
 }
 
 // Flushing a memory buffer is a no-op
-func (p *TMemoryBuffer) Flush() error {
+func (p *TMemoryBuffer) Flush(ctx context.Context) error {
 	return nil
 }
 
diff --git a/lib/go/thrift/multiplexed_protocol.go b/lib/go/thrift/multiplexed_protocol.go
index b7f4f8a..d028a30 100644
--- a/lib/go/thrift/multiplexed_protocol.go
+++ b/lib/go/thrift/multiplexed_protocol.go
@@ -19,6 +19,12 @@
 
 package thrift
 
+import (
+	"context"
+	"fmt"
+	"strings"
+)
+
 /*
 TMultiplexedProtocol is a protocol-independent concrete decorator
 that allows a Thrift client to communicate with a multiplexing Thrift server,
@@ -122,6 +128,31 @@
 	t.serviceProcessorMap[name] = processor
 }
 
+func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
+	name, typeId, seqid, err := in.ReadMessageBegin()
+	if err != nil {
+		return false, err
+	}
+	if typeId != CALL && typeId != ONEWAY {
+		return false, fmt.Errorf("Unexpected message type %v", typeId)
+	}
+	//extract the service name
+	v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2)
+	if len(v) != 2 {
+		if t.DefaultProcessor != nil {
+			smb := NewStoredMessageProtocol(in, name, typeId, seqid)
+			return t.DefaultProcessor.Process(ctx, smb, out)
+		}
+		return false, fmt.Errorf("Service name not found in message name: %s.  Did you forget to use a TMultiplexProtocol in your client?", name)
+	}
+	actualProcessor, ok := t.serviceProcessorMap[v[0]]
+	if !ok {
+		return false, fmt.Errorf("Service name not found: %s.  Did you forget to call registerProcessor()?", v[0])
+	}
+	smb := NewStoredMessageProtocol(in, v[1], typeId, seqid)
+	return actualProcessor.Process(ctx, smb, out)
+}
+
 //Protocol that use stored message for ReadMessageBegin
 type storedMessageProtocol struct {
 	TProtocol
diff --git a/lib/go/thrift/multiplexed_protocol_go17.go b/lib/go/thrift/multiplexed_protocol_go17.go
deleted file mode 100644
index c71035e..0000000
--- a/lib/go/thrift/multiplexed_protocol_go17.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import (
-	"context"
-	"fmt"
-	"strings"
-)
-
-func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	name, typeId, seqid, err := in.ReadMessageBegin()
-	if err != nil {
-		return false, err
-	}
-	if typeId != CALL && typeId != ONEWAY {
-		return false, fmt.Errorf("Unexpected message type %v", typeId)
-	}
-	//extract the service name
-	v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2)
-	if len(v) != 2 {
-		if t.DefaultProcessor != nil {
-			smb := NewStoredMessageProtocol(in, name, typeId, seqid)
-			return t.DefaultProcessor.Process(ctx, smb, out)
-		}
-		return false, fmt.Errorf("Service name not found in message name: %s.  Did you forget to use a TMultiplexProtocol in your client?", name)
-	}
-	actualProcessor, ok := t.serviceProcessorMap[v[0]]
-	if !ok {
-		return false, fmt.Errorf("Service name not found: %s.  Did you forget to call registerProcessor()?", v[0])
-	}
-	smb := NewStoredMessageProtocol(in, v[1], typeId, seqid)
-	return actualProcessor.Process(ctx, smb, out)
-}
diff --git a/lib/go/thrift/multiplexed_protocol_pre_go17.go b/lib/go/thrift/multiplexed_protocol_pre_go17.go
deleted file mode 100644
index 5c27b38..0000000
--- a/lib/go/thrift/multiplexed_protocol_pre_go17.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import (
-	"fmt"
-	"strings"
-
-	"golang.org/x/net/context"
-)
-
-func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	name, typeId, seqid, err := in.ReadMessageBegin()
-	if err != nil {
-		return false, err
-	}
-	if typeId != CALL && typeId != ONEWAY {
-		return false, fmt.Errorf("Unexpected message type %v", typeId)
-	}
-	//extract the service name
-	v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2)
-	if len(v) != 2 {
-		if t.DefaultProcessor != nil {
-			smb := NewStoredMessageProtocol(in, name, typeId, seqid)
-			return t.DefaultProcessor.Process(ctx, smb, out)
-		}
-		return false, fmt.Errorf("Service name not found in message name: %s.  Did you forget to use a TMultiplexProtocol in your client?", name)
-	}
-	actualProcessor, ok := t.serviceProcessorMap[v[0]]
-	if !ok {
-		return false, fmt.Errorf("Service name not found: %s.  Did you forget to call registerProcessor()?", v[0])
-	}
-	smb := NewStoredMessageProtocol(in, v[1], typeId, seqid)
-	return actualProcessor.Process(ctx, smb, out)
-}
diff --git a/lib/go/thrift/pre_go17.go b/lib/go/thrift/pre_go17.go
deleted file mode 100644
index cb564b8..0000000
--- a/lib/go/thrift/pre_go17.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import "golang.org/x/net/context"
-
-var defaultCtx = context.Background()
diff --git a/lib/go/thrift/processor.go b/lib/go/thrift/processor.go
deleted file mode 100644
index 566aaaf..0000000
--- a/lib/go/thrift/processor.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import "golang.org/x/net/context"
-
-// A processor is a generic object which operates upon an input stream and
-// writes to some output stream.
-type TProcessor interface {
-	Process(ctx context.Context, in, out TProtocol) (bool, TException)
-}
-
-type TProcessorFunction interface {
-	Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
-}
diff --git a/lib/go/thrift/processor_factory.go b/lib/go/thrift/processor_factory.go
index 9d645df..e4b132b 100644
--- a/lib/go/thrift/processor_factory.go
+++ b/lib/go/thrift/processor_factory.go
@@ -19,6 +19,18 @@
 
 package thrift
 
+import "context"
+
+// A processor is a generic object which operates upon an input stream and
+// writes to some output stream.
+type TProcessor interface {
+	Process(ctx context.Context, in, out TProtocol) (bool, TException)
+}
+
+type TProcessorFunction interface {
+	Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
+}
+
 // The default processor factory just returns a singleton
 // instance.
 type TProcessorFactory interface {
diff --git a/lib/go/thrift/processor_go17.go b/lib/go/thrift/processor_go17.go
deleted file mode 100644
index fb0b165..0000000
--- a/lib/go/thrift/processor_go17.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package thrift
-
-import "context"
-
-// A processor is a generic object which operates upon an input stream and
-// writes to some output stream.
-type TProcessor interface {
-	Process(ctx context.Context, in, out TProtocol) (bool, TException)
-}
-
-type TProcessorFunction interface {
-	Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
-}
diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go
index 25e6d24..615b7a4 100644
--- a/lib/go/thrift/protocol.go
+++ b/lib/go/thrift/protocol.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"errors"
 	"fmt"
 )
@@ -74,7 +75,7 @@
 	ReadBinary() (value []byte, err error)
 
 	Skip(fieldType TType) (err error)
-	Flush() (err error)
+	Flush(ctx context.Context) (err error)
 
 	Transport() TTransport
 }
diff --git a/lib/go/thrift/protocol_test.go b/lib/go/thrift/protocol_test.go
index 2573312..944055c 100644
--- a/lib/go/thrift/protocol_test.go
+++ b/lib/go/thrift/protocol_test.go
@@ -21,6 +21,7 @@
 
 import (
 	"bytes"
+	"context"
 	"io/ioutil"
 	"math"
 	"net"
@@ -31,7 +32,6 @@
 const PROTOCOL_BINARY_DATA_SIZE = 155
 
 var (
-	data           string // test data for writing
 	protocol_bdata []byte // test data for writing; same as data
 	BOOL_VALUES    []bool
 	BYTE_VALUES    []int8
@@ -47,7 +47,6 @@
 	for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ {
 		protocol_bdata[i] = byte((i + 'a') % 255)
 	}
-	data = string(protocol_bdata)
 	BOOL_VALUES = []bool{false, true, false, false, true}
 	BYTE_VALUES = []int8{117, 0, 1, 32, 127, -128, -1}
 	INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768}
@@ -120,6 +119,9 @@
 		NewTMemoryBufferTransportFactory(1024),
 		NewStreamTransportFactory(buf, buf, true),
 		NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)),
+		NewTZlibTransportFactoryWithFactory(0, NewTMemoryBufferTransportFactory(1024)),
+		NewTZlibTransportFactoryWithFactory(6, NewTMemoryBufferTransportFactory(1024)),
+		NewTZlibTransportFactoryWithFactory(9, NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024))),
 		NewTHttpPostClientTransportFactory("http://" + addr.String()),
 	}
 	for _, tf := range transports {
@@ -227,17 +229,17 @@
 	for k, v := range BOOL_VALUES {
 		err = p.WriteBool(v)
 		if err != nil {
-			t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+			t.Errorf("%s: %T %T %v Error writing bool in list at index %v: %v", "ReadWriteBool", p, trans, err, k, v)
 		}
 	}
 	p.WriteListEnd()
 	if err != nil {
-		t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+		t.Errorf("%s: %T %T %v Error writing list end: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES)
 	}
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
-		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+		t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES)
 	}
 	_, ok := p.(*TSimpleJSONProtocol)
 	if !ok {
@@ -245,16 +247,16 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteBool", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range BOOL_VALUES {
 		value, err := p.ReadBool()
 		if err != nil {
-			t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+			t.Errorf("%s: %T %T %v Error reading bool at index %v: %v", "ReadWriteBool", p, trans, err, k, v)
 		}
 		if v != value {
-			t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value)
+			t.Errorf("%s: index %v %v %v %v != %v", "ReadWriteBool", k, p, trans, v, value)
 		}
 	}
 	err = p.ReadListEnd()
@@ -280,7 +282,7 @@
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
 	}
-	err = p.Flush()
+	err = p.Flush(context.Background())
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
 	}
@@ -294,7 +296,7 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteByte", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range BYTE_VALUES {
@@ -320,7 +322,7 @@
 		p.WriteI16(v)
 	}
 	p.WriteListEnd()
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES)
@@ -331,7 +333,7 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI16", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range INT16_VALUES {
@@ -357,7 +359,7 @@
 		p.WriteI32(v)
 	}
 	p.WriteListEnd()
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES)
@@ -368,7 +370,7 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI32", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range INT32_VALUES {
@@ -393,7 +395,7 @@
 		p.WriteI64(v)
 	}
 	p.WriteListEnd()
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES)
@@ -404,7 +406,7 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI64", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range INT64_VALUES {
@@ -429,28 +431,28 @@
 		p.WriteDouble(v)
 	}
 	p.WriteListEnd()
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
-		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES)
+		t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES)
 	}
 	if thetype != thetype2 {
 		t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2)
 	}
 	if thelen != thelen2 {
-		t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2)
+		t.Errorf("%s: %T %T len %v != len %v", "ReadWriteDouble", p, trans, thelen, thelen2)
 	}
 	for k, v := range DOUBLE_VALUES {
 		value, err := p.ReadDouble()
 		if err != nil {
-			t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v)
+			t.Errorf("%s: %T %T %q Error reading double at index %d: %v", "ReadWriteDouble", p, trans, err, k, v)
 		}
 		if math.IsNaN(v) {
 			if !math.IsNaN(value) {
-				t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value)
+				t.Errorf("%s: %T %T math.IsNaN(%v) != math.IsNaN(%v)", "ReadWriteDouble", p, trans, v, value)
 			}
 		} else if v != value {
-			t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value)
+			t.Errorf("%s: %T %T %v != %v", "ReadWriteDouble", p, trans, v, value)
 		}
 	}
 	err = p.ReadListEnd()
@@ -467,7 +469,7 @@
 		p.WriteString(v)
 	}
 	p.WriteListEnd()
-	p.Flush()
+	p.Flush(context.Background())
 	thetype2, thelen2, err := p.ReadListBegin()
 	if err != nil {
 		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES)
@@ -478,7 +480,7 @@
 			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2)
 		}
 		if thelen != thelen2 {
-			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2)
+			t.Errorf("%s: %T %T len %v != len %v", "ReadWriteString", p, trans, thelen, thelen2)
 		}
 	}
 	for k, v := range STRING_VALUES {
@@ -487,7 +489,7 @@
 			t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v)
 		}
 		if v != value {
-			t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value)
+			t.Errorf("%s: %T %T %v != %v", "ReadWriteString", p, trans, v, value)
 		}
 	}
 	if err != nil {
@@ -498,7 +500,7 @@
 func ReadWriteBinary(t testing.TB, p TProtocol, trans TTransport) {
 	v := protocol_bdata
 	p.WriteBinary(v)
-	p.Flush()
+	p.Flush(context.Background())
 	value, err := p.ReadBinary()
 	if err != nil {
 		t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.Error())
diff --git a/lib/go/thrift/serializer.go b/lib/go/thrift/serializer.go
index 7712229..1ff4d37 100644
--- a/lib/go/thrift/serializer.go
+++ b/lib/go/thrift/serializer.go
@@ -19,6 +19,10 @@
 
 package thrift
 
+import (
+	"context"
+)
+
 type TSerializer struct {
 	Transport *TMemoryBuffer
 	Protocol  TProtocol
@@ -38,35 +42,35 @@
 		protocol}
 }
 
-func (t *TSerializer) WriteString(msg TStruct) (s string, err error) {
+func (t *TSerializer) WriteString(ctx context.Context, msg TStruct) (s string, err error) {
 	t.Transport.Reset()
 
 	if err = msg.Write(t.Protocol); err != nil {
 		return
 	}
 
-	if err = t.Protocol.Flush(); err != nil {
+	if err = t.Protocol.Flush(ctx); err != nil {
 		return
 	}
-	if err = t.Transport.Flush(); err != nil {
+	if err = t.Transport.Flush(ctx); err != nil {
 		return
 	}
 
 	return t.Transport.String(), nil
 }
 
-func (t *TSerializer) Write(msg TStruct) (b []byte, err error) {
+func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err error) {
 	t.Transport.Reset()
 
 	if err = msg.Write(t.Protocol); err != nil {
 		return
 	}
 
-	if err = t.Protocol.Flush(); err != nil {
+	if err = t.Protocol.Flush(ctx); err != nil {
 		return
 	}
 
-	if err = t.Transport.Flush(); err != nil {
+	if err = t.Transport.Flush(ctx); err != nil {
 		return
 	}
 
diff --git a/lib/go/thrift/serializer_test.go b/lib/go/thrift/serializer_test.go
index 06d27a1..32227ef 100644
--- a/lib/go/thrift/serializer_test.go
+++ b/lib/go/thrift/serializer_test.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"testing"
@@ -88,7 +89,7 @@
 	m.StringSet = make(map[string]struct{}, 5)
 	m.E = 2
 
-	s, err := t.WriteString(&m)
+	s, err := t.WriteString(context.Background(), &m)
 	if err != nil {
 		return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err))
 	}
@@ -122,7 +123,7 @@
 	m.StringSet = make(map[string]struct{}, 5)
 	m.E = 2
 
-	s, err := t.WriteString(&m)
+	s, err := t.WriteString(context.Background(), &m)
 	if err != nil {
 		return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err))
 
diff --git a/lib/go/thrift/serializer_types_test.go b/lib/go/thrift/serializer_types_test.go
index e6f8180..e5472bb 100644
--- a/lib/go/thrift/serializer_types_test.go
+++ b/lib/go/thrift/serializer_types_test.go
@@ -19,7 +19,7 @@
 
 package thrift
 
-// Autogenerated by Thrift Compiler (0.11.0)
+// Autogenerated by Thrift Compiler (FIXME)
 // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 
 /* THE FOLLOWING THRIFT FILE WAS USED TO CREATE THIS
diff --git a/lib/go/thrift/server_socket.go b/lib/go/thrift/server_socket.go
index 80313c4..7dd24ae 100644
--- a/lib/go/thrift/server_socket.go
+++ b/lib/go/thrift/server_socket.go
@@ -75,7 +75,9 @@
 		return nil, errTransportInterrupted
 	}
 
+	p.mu.Lock()
 	listener := p.listener
+	p.mu.Unlock()
 	if listener == nil {
 		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
 	}
@@ -115,19 +117,20 @@
 }
 
 func (p *TServerSocket) Close() error {
-	defer func() {
-		p.listener = nil
-	}()
+	var err error
+	p.mu.Lock()
 	if p.IsListening() {
-		return p.listener.Close()
+		err = p.listener.Close()
+		p.listener = nil
 	}
-	return nil
+	p.mu.Unlock()
+	return err
 }
 
 func (p *TServerSocket) Interrupt() error {
 	p.mu.Lock()
-	defer p.mu.Unlock()
 	p.interrupted = true
+	p.mu.Unlock()
 	p.Close()
 
 	return nil
diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go
index 7353322..2e8a711 100644
--- a/lib/go/thrift/simple_json_protocol.go
+++ b/lib/go/thrift/simple_json_protocol.go
@@ -22,6 +22,7 @@
 import (
 	"bufio"
 	"bytes"
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
@@ -552,7 +553,7 @@
 	return v, p.ParsePostValue()
 }
 
-func (p *TSimpleJSONProtocol) Flush() (err error) {
+func (p *TSimpleJSONProtocol) Flush(ctx context.Context) (err error) {
 	return NewTProtocolException(p.writer.Flush())
 }
 
@@ -1064,7 +1065,7 @@
 	for _, char := range line {
 		switch char {
 		default:
-			e := fmt.Errorf("Expecting end of list \"]\", but found: \"", line, "\"")
+			e := fmt.Errorf("Expecting end of list \"]\", but found: \"%v\"", line)
 			return NewTProtocolExceptionWithType(INVALID_DATA, e)
 		case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]):
 			break
diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go
index 8f0dcc9..7b98082 100644
--- a/lib/go/thrift/simple_json_protocol_test.go
+++ b/lib/go/thrift/simple_json_protocol_test.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
@@ -37,7 +38,7 @@
 		if e := p.WriteBool(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -63,7 +64,7 @@
 		} else {
 			trans.Write(JSON_FALSE)
 		}
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadBool()
 		if e != nil {
@@ -88,7 +89,7 @@
 		if e := p.WriteByte(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -110,7 +111,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTSimpleJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadByte()
 		if e != nil {
@@ -135,7 +136,7 @@
 		if e := p.WriteI16(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -157,7 +158,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTSimpleJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI16()
 		if e != nil {
@@ -182,7 +183,7 @@
 		if e := p.WriteI32(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -204,7 +205,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTSimpleJSONProtocol(trans)
 		trans.WriteString(strconv.Itoa(int(value)))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI32()
 		if e != nil {
@@ -228,7 +229,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTSimpleJSONProtocol(trans)
 	trans.WriteString(value)
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	v, e := p.ReadI32()
 
@@ -250,7 +251,7 @@
 		if e := p.WriteI64(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -272,7 +273,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTSimpleJSONProtocol(trans)
 		trans.WriteString(strconv.FormatInt(value, 10))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadI64()
 		if e != nil {
@@ -296,7 +297,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTSimpleJSONProtocol(trans)
 	trans.WriteString(value)
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	v, e := p.ReadI64()
 
@@ -318,7 +319,7 @@
 		if e := p.WriteDouble(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -355,7 +356,7 @@
 		p := NewTSimpleJSONProtocol(trans)
 		n := NewNumericFromDouble(value)
 		trans.WriteString(n.String())
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadDouble()
 		if e != nil {
@@ -394,7 +395,7 @@
 		if e := p.WriteString(value); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 		}
-		if e := p.Flush(); e != nil {
+		if e := p.Flush(context.Background()); e != nil {
 			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 		}
 		s := trans.String()
@@ -416,7 +417,7 @@
 		trans := NewTMemoryBuffer()
 		p := NewTSimpleJSONProtocol(trans)
 		trans.WriteString(jsonQuote(value))
-		trans.Flush()
+		trans.Flush(context.Background())
 		s := trans.String()
 		v, e := p.ReadString()
 		if e != nil {
@@ -440,7 +441,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTSimpleJSONProtocol(trans)
 	trans.WriteString(value)
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	v, e := p.ReadString()
 	if e != nil {
@@ -464,7 +465,7 @@
 	if e := p.WriteBinary(value); e != nil {
 		t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
 	}
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
 	}
 	s := trans.String()
@@ -487,7 +488,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTSimpleJSONProtocol(trans)
 	trans.WriteString(jsonQuote(b64String))
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	v, e := p.ReadBinary()
 	if e != nil {
@@ -516,7 +517,7 @@
 	trans := NewTMemoryBuffer()
 	p := NewTSimpleJSONProtocol(trans)
 	trans.WriteString(value)
-	trans.Flush()
+	trans.Flush(context.Background())
 	s := trans.String()
 	b, e := p.ReadBinary()
 	v := string(b)
@@ -542,7 +543,7 @@
 		}
 	}
 	p.WriteListEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
@@ -596,7 +597,7 @@
 		}
 	}
 	p.WriteSetEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
@@ -653,12 +654,12 @@
 		}
 	}
 	p.WriteMapEnd()
-	if e := p.Flush(); e != nil {
+	if e := p.Flush(context.Background()); e != nil {
 		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
 	}
 	str := trans.String()
 	if str[0] != '[' || str[len(str)-1] != ']' {
-		t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES)
+		t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES)
 	}
 	l := strings.Split(str[1:len(str)-1], ",")
 	if len(l) < 3 {
diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go
index 37081bd..6035802 100644
--- a/lib/go/thrift/simple_server.go
+++ b/lib/go/thrift/simple_server.go
@@ -125,26 +125,38 @@
 	return p.serverTransport.Listen()
 }
 
+func (p *TSimpleServer) innerAccept() (int32, error) {
+	client, err := p.serverTransport.Accept()
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	closed := atomic.LoadInt32(&p.closed)
+	if closed != 0 {
+		return closed, nil
+	}
+	if err != nil {
+		return 0, err
+	}
+	if client != nil {
+		p.wg.Add(1)
+		go func() {
+			defer p.wg.Done()
+			if err := p.processRequests(client); err != nil {
+				log.Println("error processing request:", err)
+			}
+		}()
+	}
+	return 0, nil
+}
+
 func (p *TSimpleServer) AcceptLoop() error {
 	for {
-		client, err := p.serverTransport.Accept()
-		p.mu.Lock()
-		if atomic.LoadInt32(&p.closed) != 0 {
-			return nil
-		}
+		closed, err := p.innerAccept()
 		if err != nil {
 			return err
 		}
-		if client != nil {
-			p.wg.Add(1)
-			go func() {
-				defer p.wg.Done()
-				if err := p.processRequests(client); err != nil {
-					log.Println("error processing request:", err)
-				}
-			}()
+		if closed != 0 {
+			return nil
 		}
-		p.mu.Unlock()
 	}
 }
 
diff --git a/lib/go/thrift/simple_server_test.go b/lib/go/thrift/simple_server_test.go
index 25702e4..58149a8 100644
--- a/lib/go/thrift/simple_server_test.go
+++ b/lib/go/thrift/simple_server_test.go
@@ -21,7 +21,8 @@
 
 import (
 	"testing"
-	"time"
+	"errors"
+	"runtime"
 )
 
 type mockServerTransport struct {
@@ -122,6 +123,34 @@
 
 	serv := NewTSimpleServer2(proc, trans)
 	go serv.Serve()
-	time.Sleep(1)
+	runtime.Gosched()
+	serv.Stop()
+}
+
+func TestNoHangDuringStopFromDanglingLockAcquireDuringAcceptLoop(t *testing.T) {
+	proc := &mockProcessor{
+		ProcessFunc: func(in, out TProtocol) (bool, TException) {
+			return false, nil
+		},
+	}
+
+	trans := &mockServerTransport{
+		ListenFunc: func() error {
+			return nil
+		},
+		AcceptFunc: func() (TTransport, error) {
+			return nil, errors.New("no sir")
+		},
+		CloseFunc: func() error {
+			return nil
+		},
+		InterruptFunc: func() error {
+			return nil
+		},
+	}
+
+	serv := NewTSimpleServer2(proc, trans)
+	go serv.Serve()
+	runtime.Gosched()
 	serv.Stop()
 }
diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go
index 383b1fe..8854279 100644
--- a/lib/go/thrift/socket.go
+++ b/lib/go/thrift/socket.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"net"
 	"time"
 )
@@ -148,7 +149,7 @@
 	return p.conn.Write(buf)
 }
 
-func (p *TSocket) Flush() error {
+func (p *TSocket) Flush(ctx context.Context) error {
 	return nil
 }
 
diff --git a/lib/go/thrift/ssl_socket.go b/lib/go/thrift/ssl_socket.go
index c3bd72c..ba63377 100644
--- a/lib/go/thrift/ssl_socket.go
+++ b/lib/go/thrift/ssl_socket.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"crypto/tls"
 	"net"
 	"time"
@@ -158,7 +159,7 @@
 	return p.conn.Write(buf)
 }
 
-func (p *TSSLSocket) Flush() error {
+func (p *TSSLSocket) Flush(ctx context.Context) error {
 	return nil
 }
 
diff --git a/lib/go/thrift/transport.go b/lib/go/thrift/transport.go
index 70a85a8..ba2738a 100644
--- a/lib/go/thrift/transport.go
+++ b/lib/go/thrift/transport.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"errors"
 	"io"
 )
@@ -30,6 +31,10 @@
 	Flush() (err error)
 }
 
+type ContextFlusher interface {
+	Flush(ctx context.Context) (err error)
+}
+
 type ReadSizeProvider interface {
 	RemainingBytes() (num_bytes uint64)
 }
@@ -37,7 +42,7 @@
 // Encapsulates the I/O layer
 type TTransport interface {
 	io.ReadWriteCloser
-	Flusher
+	ContextFlusher
 	ReadSizeProvider
 
 	// Opens the transport for communication
@@ -60,6 +65,6 @@
 	io.ByteReader
 	io.ByteWriter
 	stringWriter
-	Flusher
+	ContextFlusher
 	ReadSizeProvider
 }
diff --git a/lib/go/thrift/transport_test.go b/lib/go/thrift/transport_test.go
index 864958a..0127803 100644
--- a/lib/go/thrift/transport_test.go
+++ b/lib/go/thrift/transport_test.go
@@ -20,6 +20,7 @@
 package thrift
 
 import (
+	"context"
 	"io"
 	"net"
 	"strconv"
@@ -54,7 +55,7 @@
 	if err != nil {
 		t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err)
 	}
-	err = writeTrans.Flush()
+	err = writeTrans.Flush(context.Background())
 	if err != nil {
 		t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err)
 	}
@@ -74,7 +75,7 @@
 	if err != nil {
 		t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err)
 	}
-	err = writeTrans.Flush()
+	err = writeTrans.Flush(context.Background())
 	if err != nil {
 		t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err)
 	}
@@ -113,7 +114,7 @@
 	if err != nil {
 		t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err)
 	}
-	err = writeTrans.Flush()
+	err = writeTrans.Flush(context.Background())
 	if err != nil {
 		t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err)
 	}
diff --git a/lib/go/thrift/zlib_transport.go b/lib/go/thrift/zlib_transport.go
index f2f0732..f3d4267 100644
--- a/lib/go/thrift/zlib_transport.go
+++ b/lib/go/thrift/zlib_transport.go
@@ -21,6 +21,7 @@
 
 import (
 	"compress/zlib"
+	"context"
 	"io"
 	"log"
 )
@@ -91,11 +92,11 @@
 }
 
 // Flush flushes the writer and its underlying transport.
-func (z *TZlibTransport) Flush() error {
+func (z *TZlibTransport) Flush(ctx context.Context) error {
 	if err := z.writer.Flush(); err != nil {
 		return err
 	}
-	return z.transport.Flush()
+	return z.transport.Flush(ctx)
 }
 
 // IsOpen returns true if the transport is open
diff --git a/lib/haxe/README.md b/lib/haxe/README.md
index ac70f25..e74b773 100644
--- a/lib/haxe/README.md
+++ b/lib/haxe/README.md
@@ -69,10 +69,10 @@
 Thrift Haxe bindings can be set up via the `haxelib` tool  
 either from the official ASF repo, or via the github mirror.
 
-- To set up any **stable version**, choose the appropriate branch (e.g. `0.11.0`):
+- To set up any **stable version**, choose the appropriate branch (e.g. `1.0.0`, etc.):
 
-    - `haxelib git thrift https://git.apache.org/thrift.git 0.11.0 lib/haxe`
-    - `haxelib git thrift https://github.com/apache/thrift.git 0.11.0 lib/haxe`
+    - `haxelib git thrift https://git.apache.org/thrift.git 1.0.0 lib/haxe`
+    - `haxelib git thrift https://github.com/apache/thrift.git 1.0.0 lib/haxe`
 
 - To set up the current **development version**, use the `master` branch:
   
diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json
index 26caa79..992ad90 100644
--- a/lib/haxe/haxelib.json
+++ b/lib/haxe/haxelib.json
@@ -4,7 +4,7 @@
 	"license": "Apache",
 	"tags": ["thrift", "rpc", "serialization", "cross", "framework"],
 	"description": "Haxe bindings for the Apache Thrift RPC and serialization framework",
-	"version": "0.11.0",
+	"version": "1.0.0",
 	"releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.",
 	"contributors": ["Apache Software Foundation (ASF)"],
 	"dependencies": { },
diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal
index 5830679..5515556 100644
--- a/lib/hs/thrift.cabal
+++ b/lib/hs/thrift.cabal
@@ -18,8 +18,8 @@
 --
 
 Name:           thrift
-Version:        0.11.0
-Cabal-Version:  >= 1.8
+Version:        1.0.0
+Cabal-Version:  1.24
 License:        OtherLicense
 Category:       Foreign
 Build-Type:     Simple
@@ -63,7 +63,8 @@
     Thrift.Transport.IOBuffer,
     Thrift.Transport.Memory,
     Thrift.Types
-  Extensions:
+  Default-Language: Haskell2010
+  Default-Extensions:
     DeriveDataTypeable,
     ExistentialQuantification,
     FlexibleInstances,
@@ -80,3 +81,4 @@
   Ghc-Options: -Wall
   main-is: Spec.hs
   Build-Depends: base, thrift, hspec, QuickCheck >= 2.8.2, bytestring >= 0.10, unordered-containers >= 0.2.6
+  Default-Language: Haskell2010
diff --git a/lib/java/CMakeLists.txt b/lib/java/CMakeLists.txt
index f7a1a63..46064e6 100644
--- a/lib/java/CMakeLists.txt
+++ b/lib/java/CMakeLists.txt
@@ -17,19 +17,14 @@
 # under the License.
 #
 
-file(GLOB java_sources src/**/*.java)
-
 if(ANDROID)
-    set(android_sources
-        android/build.gradle
-        android/settings.gradle
-        android/src/main/AndroidManifest.xml
-    )
     set(THRIFT_AAR outputs/aar/thrift-debug.aar outputs/aar/thrift-release.aar)
     add_custom_command(
         OUTPUT ${THRIFT_AAR}
-        COMMAND ${GRADLE_EXECUTABLE} -p"${CMAKE_CURRENT_SOURCE_DIR}/android" -PbuildDir="${CMAKE_CURRENT_BINARY_DIR}" assemble
-        DEPENDS ${java_sources} ${android_sources})
+        COMMAND ${GRADLE_EXECUTABLE}
+            -p "${CMAKE_CURRENT_SOURCE_DIR}/android"
+            "-PbuildDir=${CMAKE_CURRENT_BINARY_DIR}/android/build" assemble
+    )
     add_custom_target(thrift_aar ALL DEPENDS ${THRIFT_AAR})
 
 else(ANDROID)
@@ -46,35 +41,47 @@
         set(JAVA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/java")
     endif()
 
-    file(GLOB_RECURSE ThriftJava_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.java)
-    set(ThriftJava_ARTIFACTS
-        libthrift-${thrift_VERSION}.jar
-        libthrift-${thrift_VERSION}.pom
-    )
-    add_custom_command(
-        OUTPUT ${ThriftJava_ARTIFACTS}
-        COMMAND ${Ant_EXECUTABLE} ${ANT_FLAGS} -Dbuild.dir="${CMAKE_CURRENT_BINARY_DIR}" -f build.xml
-        MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/build.xml
-        DEPENDS ${ThriftJava_SOURCES}
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    )
-
     add_custom_target(ThriftJava ALL
-        COMMENT "Building Java library using Ant"
-        DEPENDS ${ThriftJava_ARTIFACTS}
+        COMMENT "Building Java library using Gradle Wrapper"
+        COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} assemble
+            --console=plain --no-daemon
+            -Prelease=true
+            -Pthrift.version=${thrift_VERSION}
+            "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build"
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
     )
 
-    # Hook the ant install task into CMake install
-    install(CODE "execute_process(
-        COMMAND ${Ant_EXECUTABLE} ${ANT_FLAGS} install
-        -Dbuild.dir=\"${CMAKE_CURRENT_BINARY_DIR}\"
-        -Dinstall.path=\"${JAVA_INSTALL_DIR}\" -Dinstall.javadoc.path=\"${JAVA_DOC_INSTALL_DIR}\" -f build.xml
+    # Enable publishing from CMake if the publishing information is provided
+    add_custom_target(MavenPublish
+        COMMENT "Publishing Java Library to Apache Maven staging"
+        COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} clean uploadArchives
+            --console=plain --no-daemon
+            -Prelease=true
+            -Pthrift.version=${thrift_VERSION}
+            "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build"
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    )")
+    )
+
+    # Hook the CMake install process to the results from make ALL.
+    # This works best when 'make all && sudo make install/fast' is used.
+    # Using slash to end the source location to avoid copying the directory path.
+    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/libs/
+            DESTINATION ${JAVA_INSTALL_DIR}
+            FILES_MATCHING PATTERN "libthrift-${thrift_VERSION}.jar")
+    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/deps/
+            DESTINATION ${JAVA_INSTALL_DIR}
+            FILES_MATCHING PATTERN "*.jar")
+    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/docs/javadoc/
+            DESTINATION ${JAVA_DOC_INSTALL_DIR})
 
     if(BUILD_TESTING)
         add_test(NAME JavaTest
-                 COMMAND ${Ant_EXECUTABLE} ${ANT_FLAGS} -Dbuild.dir=${CMAKE_CURRENT_BINARY_DIR} -Dthrift.compiler=${THRIFT_COMPILER} -f build.xml test
-                 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+                COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} test
+                    --console=plain --no-daemon
+                    -Prelease=true
+                    -Pthrift.version=${thrift_VERSION}
+                    "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build"
+                    "-Pthrift.compiler=${THRIFT_COMPILER}"
+                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
     endif()
 endif(ANDROID)
diff --git a/lib/java/Makefile.am b/lib/java/Makefile.am
index 1c867ae..65981ca 100644
--- a/lib/java/Makefile.am
+++ b/lib/java/Makefile.am
@@ -20,29 +20,53 @@
 export CLASSPATH
 
 all-local:
-	$(ANT) $(ANT_FLAGS)
+	./gradlew $(GRADLE_OPTS) assemble \
+		-Prelease=true \
+		-Pthrift.version=$(PACKAGE_VERSION) \
+		--console=plain
 
 install-exec-hook:
-	$(ANT) $(ANT_FLAGS) install -Dinstall.path=$(DESTDIR)$(JAVA_PREFIX) \
-		-Dinstall.javadoc.path=$(DESTDIR)$(docdir)/java
+	./gradlew $(GRADLE_OPTS) install \
+		-Prelease=true \
+		-Pinstall.path=$(DESTDIR)$(JAVA_PREFIX) \
+		-Pinstall.javadoc.path=$(DESTDIR)$(docdir)/java \
+		-Pthrift.version=$(PACKAGE_VERSION) \
+		--console=plain
 
-# Make sure this doesn't fail if ant is not configured.
 clean-local:
-	ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \
-	$$ANT $(ANT_FLAGS) clean
+	./gradlew $(GRADLE_OPTS) clean --console=plain
 
 precross: $(THRIFT)
-	$(ANT) $(ANT_FLAGS) compile-test
+	./gradlew $(GRADLE_OPTS) shadowJar \
+		-Prelease=true \
+		-Pthrift.version=$(PACKAGE_VERSION) \
+		-Pthrift.compiler=$(THRIFT) \
+		--console=plain
 
-check-local: all
-	$(ANT) $(ANT_FLAGS) test
+check-local: $(THRIFT)
+	./gradlew $(GRADLE_OPTS) test \
+		-Prelease=true \
+		-Pthrift.version=$(PACKAGE_VERSION) \
+		-Pthrift.compiler=$(THRIFT) \
+		--console=plain
+
+maven-publish:
+	./gradlew $(GRADLE_OPTS) uploadArchives \
+		-Prelease=true \
+		-Pthrift.version=$(PACKAGE_VERSION) \
+		--console=plain
 
 EXTRA_DIST = \
-	build.xml \
-	build.properties \
+	build.gradle \
+	gradle.properties \
+	settings.gradle \
+	gradle \
+	gradlew \
+	gradlew.bat \
 	CMakeLists.txt \
 	coding_standards.md \
 	android \
 	src \
 	test \
+	code_quality_tools \
 	README.md
diff --git a/lib/java/README.md b/lib/java/README.md
index 66bcfa5..0b5f0d8 100644
--- a/lib/java/README.md
+++ b/lib/java/README.md
@@ -20,18 +20,59 @@
 specific language governing permissions and limitations
 under the License.
 
-Using Thrift with Java
-======================
+Building and installing from source
+===================================
+
+When using a CMake build from the source distribution on Linux the
+easiest way to build and install is this simple command line:
+
+    make all && sudo make install/fast
+
+It is important to use the install/fast option to eliminate
+the automatic rebuild by dependency that causes issues because
+the build tooling is designed to work with cached files in the
+user home directory during the build process. Instead this builds
+the code in the expected local build tree and then uses CMake
+install code to copy to the target destination.
+
+Building Thrift with Gradle without CMake/Autoconf
+==================================================
 
 The Thrift Java source is not build using the GNU tools, but rather uses
-the Apache Ant build system, which tends to be predominant amongst Java
+the Gradle build system, which tends to be predominant amongst Java
 developers.
 
 To compile the Java Thrift libraries, simply do the following:
 
-    ant
+    ./gradlew
 
-Yep, that's easy. Look for libthrift.jar in the base directory.
+Yep, that's easy. Look for libthrift-<version>.jar in the build/libs directory.
+
+The default build will run the unit tests which expect a usable
+Thrift compiler to exist on the system. You have two choices for
+that.
+
+* Build the Thrift executable from source at the default
+  location in the source tree. The project is configured
+  to look for it there.
+* Install the published binary distribution to have Thrift
+  executable in a known location and add the path to the
+  ~/.gradle/gradle.properties file using the property name
+  "thrift.compiler". For example this would set the path in
+  a Windows box if Thrift was installed under C:\Thrift
+
+    thrift.compiler=C:/Thrift/thrift.exe
+
+To just build the library without running unit tests you simply do this.
+
+    ./gradlew assemble
+
+To install the library in the local Maven repository location
+where other Maven or Gradle builds can reference it simply do this.
+
+    ./gradlew install
+
+The library will be placed in your home directory under .m2/repository
 
 To include Thrift in your applications simply add libthrift.jar to your
 classpath, or install if in your default system classpath of choice.
@@ -39,15 +80,97 @@
 
 Build Thrift behind a proxy:
 
-    ant -Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret
+    ./gradlew -Dhttp.proxyHost=myproxyhost -Dhttp.proxyPort=8080 -Dhttp.proxyUser=thriftuser -Dhttp.proxyPassword=topsecret
 
 or via
 
-    ./configure --with-java ANT_FLAGS='-Dproxy.enabled=1 -Dproxy.host=myproxyhost -Dproxy.user=thriftuser -Dproxy.pass=topsecret'
+    ./configure --with-java GRADLE_OPTS='-Dhttp.proxyHost=myproxyhost -Dhttp.proxyPort=8080 -Dhttp.proxyUser=thriftuser -Dhttp.proxyPassword=topsecret'
+
+
+Unit Test HTML Reports
+======================
+
+The build will automatically generate an HTML Unit Test report. This can be found
+under build/reports/tests/test/index.html. It can be viewed with a browser
+directly from that location.
+
+
+Clover Code Coverage for Thrift
+===============================
+
+The build will optionally generate Clover Code coverage if the Gradle property
+`cloverEnabled=true` is set in ~/.gradle/gradle.properties or on the command line
+via `-PcloverEnabled=true`. The generated report can be found under the location
+build/reports/clover/html/index.html. It can be viewed with a browser
+directly from that location. Additionally, a PDF report is generated and is found
+under the location build/reports/clover/clover.pdf.
+
+The following command will build, unit test, and generate Clover reports:
+
+    ./gradlew -PcloverEnabled=true
+
+
+Publishing Maven Artifacts to Maven Central
+===========================================
+
+The Automake build generates a Makefile that provides the correct parameters
+when you run the build provided the configure.ac has been set with the correct
+version number. The Gradle build will receive the correct value for the build.
+The same applies to the CMake build, the value from the configure.ac file will
+be used if you execute these commands:
+
+    make maven-publish   -- This is for an Automake Linux build
+    make MavenPublish    -- This is for a CMake generated build
+
+The uploadArchives task in Gradle is preconfigured with all necessary details
+to sign and publish the artifacts from the build to the Apache Maven staging
+repository. The task requires the following externally provided properties to
+authenticate to the repository and sign the artifacts. The preferred approach
+is to create or edit the ~/.gradle/gradle.properties file and add the following
+properties to it.
+
+    # Signing key information for artifacts PGP signature (values are examples)
+    signing.keyId=24875D73
+    signing.password=secret
+    signing.secretKeyRingFile=/Users/me/.gnupg/secring.gpg
+
+    # Apache Maven staging repository user credentials
+    mavenUser=meMyselfAndI
+    mavenPassword=MySuperAwesomeSecretPassword
+
+It is also possible to manually publish using the Gradle build directly.
+With the key information and credentials in place the following will generate
+if needed the build artifacts and proceed to publish the results.
+
+    ./gradlew -Prelease=true -Pthrift.version=0.11.0 uploadArchives
+
+It is also possible to override the target repository for the Maven Publication
+by using a Gradle property, for example you can publish signed JAR files to your
+company internal server if you add this to the command line or in the
+~/.gradle/gradle.properties file. The URL below assumes a Nexus Repository.
+
+    maven-repository-url=https://my.company.com/service/local/staging/deploy/maven2
+
+Or the same on the command line:
+
+    ./gradlew -Pmaven-repository-url=https://my.company.com/service/local/staging/deploy/maven2 -Prelease=true -Pthrift.version=0.11.0 uploadArchives
 
 
 Dependencies
 ============
 
-Apache Ant
-http://ant.apache.org/
+Gradle
+http://gradle.org/
+
+# Breaking Changes
+
+## 0.12.0
+
+The access modifier of the AutoExpandingBuffer class has been changed from
+public to default (package) and will no longer be accessible by third-party
+libraries.
+
+The access modifier of the ShortStack class has been changed from
+public to default (package) and will no longer be accessible by third-party
+libraries.
+
diff --git a/lib/java/android/build.gradle b/lib/java/android/build.gradle
index 4aa2864..c998423 100644
--- a/lib/java/android/build.gradle
+++ b/lib/java/android/build.gradle
@@ -20,31 +20,31 @@
 apply plugin: 'com.android.library'
 
 android {
-  compileSdkVersion 23
-  buildToolsVersion "23.0.1"
-  useLibrary 'org.apache.http.legacy'
-  sourceSets.main.java {
-    srcDir '../src'
-    exclude 'org/apache/thrift/transport/TSaslClientTransport.java'
-    exclude 'org/apache/thrift/transport/TSaslServerTransport.java'
-    exclude 'org/apache/thrift/transport/TSaslTransport.java'
-  }
+    compileSdkVersion 23
+    buildToolsVersion "23.0.1"
+    useLibrary 'org.apache.http.legacy'
+    sourceSets.main.java {
+        srcDir '../src'
+        exclude 'org/apache/thrift/transport/TSaslClientTransport.java'
+        exclude 'org/apache/thrift/transport/TSaslServerTransport.java'
+        exclude 'org/apache/thrift/transport/TSaslTransport.java'
+    }
 }
 
 repositories {
-  mavenCentral()
+    mavenCentral()
 }
 dependencies {
-  compile 'org.slf4j:slf4j-api:1.7.13'
-  compile 'javax.servlet:servlet-api:2.5'
-  compile 'org.apache.httpcomponents:httpcore:4.4.4'
+    compile 'org.slf4j:slf4j-api:1.7.13'
+    compile 'javax.servlet:servlet-api:2.5'
+    compile 'org.apache.httpcomponents:httpcore:4.4.4'
 }
 
 buildscript {
-  repositories {
-    mavenCentral()
-  }
-  dependencies {
-    classpath 'com.android.tools.build:gradle:1.5.0'
-  }
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.5.0'
+    }
 }
diff --git a/lib/java/build.gradle b/lib/java/build.gradle
new file mode 100644
index 0000000..4302f77
--- /dev/null
+++ b/lib/java/build.gradle
@@ -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.
+ */
+
+// Using the legacy plugin classpath for Clover so it can be loaded optionally
+buildscript {
+    repositories {
+        google()
+        jcenter()
+        gradlePluginPortal()
+    }
+
+    dependencies {
+        classpath 'com.bmuschko:gradle-clover-plugin:2.2.0'
+    }
+}
+
+plugins {
+    id 'java'
+    id 'maven'
+    id 'signing'
+    id 'com.github.johnrengelman.shadow' version '2.0.2'
+}
+
+description = 'Apache Thrift Java Library'
+
+defaultTasks 'build'
+
+// Version components for this project
+group = property('thrift.groupid')
+
+// Drop the -dev suffix, we use the SNAPSHOT suffix for non-release versions
+def parsedVersion = property('thrift.version').toString().replace('-dev', '')
+if (Boolean.parseBoolean(project.release)) {
+    version = parsedVersion
+} else {
+    version = parsedVersion + '-SNAPSHOT'
+}
+
+// Keeping the rest of the build logic in functional named scripts for clarity
+apply from: 'gradle/environment.gradle'
+apply from: 'gradle/sourceConfiguration.gradle'
+apply from: 'gradle/additionalArtifacts.gradle'
+apply from: 'gradle/generateTestThrift.gradle'
+apply from: 'gradle/unitTests.gradle'
+apply from: 'gradle/cloverCoverage.gradle'
+apply from: 'gradle/functionalTests.gradle'
+apply from: 'gradle/publishing.gradle'
+apply from: 'gradle/codeQualityChecks.gradle'
diff --git a/lib/java/build.properties b/lib/java/build.properties
deleted file mode 100644
index fd35351..0000000
--- a/lib/java/build.properties
+++ /dev/null
@@ -1,31 +0,0 @@
-thrift.version=0.11.0
-thrift.groupid=org.apache.thrift
-release=false
-
-# Jar Versions 
-mvn.ant.task.version=2.1.3
-
-# Local Install paths
-install.path=/usr/local/lib
-install.javadoc.path=${install.path}
-
-# Maven dependency download locations
-mvn.repo=http://repo1.maven.org/maven2
-apache.repo=https://repository.apache.org/content/repositories/releases
-mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version}
-mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar
-
-# Apache Maven publish 
-license=http://www.apache.org/licenses/LICENSE-2.0.txt
-maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2
-maven-repository-id=apache.releases.https
-
-# Jar Versions 
-mvn.ant.task.version=2.1.3
-
-# Dependency versions
-httpclient.version=4.4.1
-httpcore.version=4.4.1
-slf4j.version=1.7.12
-servlet.version=2.5
-
diff --git a/lib/java/build.xml b/lib/java/build.xml
deleted file mode 100644
index 512aec7..0000000
--- a/lib/java/build.xml
+++ /dev/null
@@ -1,421 +0,0 @@
-<?xml version="1.0"?>
-<!--
- 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.
- -->
-<project name="libthrift" default="dist" basedir="."
-  xmlns:artifact="antlib:org.apache.maven.artifact.ant">
-
-  <description>Thrift Build File</description>
-  <property name="thrift.root" location="../../"/>
-  <property name="thrift.artifactid" value="libthrift"/>
-
-  <!-- Include the base properties file -->
-  <property file="${basedir}/build.properties" />
-
-  <property environment="env"/>
-
-  <condition property="version" value="${thrift.version}">
-    <isset property="release"/>
-  </condition>
-  <property name="version" value="${thrift.version}-snapshot"/>
-
-  <property name="final.name" value="${thrift.artifactid}-${version}"/>
-
-  <property name="thrift.compiler" location="../../compiler/cpp/thrift"/>
-  <property name="src" location="${basedir}/src"/>
-  <property name="build.dir" location="${basedir}/build"/>
-  <property name="build.lib.dir" location="${build.dir}/lib"/>
-  <property name="build.tools.dir" location="${build.dir}/tools"/>
-  <property name="src.test" location="test"/>
-  <property name="javadoc.dir" location="${build.dir}/javadoc"/>
-  <property name="build.test.dir" location="${build.dir}/test"/>
-  <property name="test.thrift.home" location="${thrift.root}/test"/>
-
-  <property name="gen" location="gen-java"/>
-  <property name="genbean" location="gen-javabean"/>
-  <property name="genreuse" location="gen-javareuse"/>
-  <property name="genfullcamel" location="gen-fullcamel"/>
-
-  <property name="jar.file" location="${build.dir}/${final.name}.jar"/>
-  <property name="test.jar.file" location="${build.dir}/${final.name}-test.jar"/>
-  <property name="javadoc.jar.file" location="${build.dir}/${final.name}-javadoc.jar"/>
-  <property name="source.jar.file" location="${build.dir}/${final.name}-sources.jar"/>
-
-  <!-- Junit properties -->
-  <property name="test.junit.output.format" value="plain"/>
-  <property name="test.timeout" value="2000000"/>
-  <property name="test.src.dir" location="${basedir}/test"/>
-  <property name="test.log.dir" value="${build.test.dir}/log"/>
-  <property name="test.port" value="9090"/>
-
-  <!-- maven properties -->
-  <property name="pom.xml" location="${build.dir}/${final.name}.pom"/>
-
-  <path id="compile.classpath">
-    <fileset dir="${build.lib.dir}">
-      <include name="**/*.jar"/>
-    </fileset>
-  </path>
-
-  <path id="test.classpath">
-    <path refid="compile.classpath"/>
-    <pathelement path="${env.CLASSPATH}"/>
-    <pathelement location="${build.test.dir}"/>
-    <pathelement location="${jar.file}"/>
-    <pathelement location="${test.jar.file}"/>
-
-  </path>
-
-  <!-- Tasks -->
-  <target name="init" depends="setup.init,mvn.init" unless="init.finished">
-    <property name="init.finished" value="true"/>
-  </target>
-
-  <target name="setup.init">
-    <tstamp/>
-    <mkdir dir="${build.dir}"/>
-    <mkdir dir="${build.lib.dir}"/>
-    <mkdir dir="${build.tools.dir}"/>
-    <mkdir dir="${build.test.dir}"/>
-  </target>
-
-  <target name="compile" depends="init">
-    <javac compiler="modern" srcdir="${src}" destdir="${build.dir}" source="1.5" target="1.5"
-    debug="true" classpathref="compile.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:unchecked"/>
-    </javac>
-  </target>
-
-  <target name="javadoc" depends="init">
-    <javadoc sourcepath="${src}" destdir="${javadoc.dir}"
-      version="true" windowtitle="Thrift Java API" doctitle="Thrift Java API"
-      classpathref="test.classpath">
-    </javadoc>
-    <jar jarfile="${javadoc.jar.file}" basedir="${javadoc.dir}">
-      <manifest>
-        <attribute name="Implementation-Version" value="${version}"/>
-      </manifest>
-    </jar>
-  </target>
-
-  <target name="dist" depends="compile">
-    <mkdir dir="${build.dir}/META-INF"/>
-    <copy file="${thrift.root}/LICENSE" tofile="${build.dir}/META-INF/LICENSE.txt"/>
-    <copy file="${thrift.root}/NOTICE" tofile="${build.dir}/META-INF/NOTICE.txt"/>
-    <jar jarfile="${jar.file}">
-      <manifest>
-        <attribute name="Implementation-Version" value="${version}"/>
-        <attribute name="Bundle-ManifestVersion" value="2"/>
-        <attribute name="Bundle-SymbolicName" value="${thrift.groupid}"/>
-        <attribute name="Bundle-Name" value="Apache Thrift"/>
-        <attribute name="Bundle-Version" value="${version}"/>
-        <attribute name="Bundle-Description" value="Apache Thrift library"/>
-        <attribute name="Bundle-License" value="${license}"/>
-        <attribute name="Bundle-ActivationPolicy" value="lazy"/>
-        <attribute name="Export-Package" value="${thrift.groupid}.async;uses:=&quot;${thrift.groupid}.protocol,${thrift.groupid}.transport,org.slf4j,${thrift.groupid}&quot;;version=&quot;${version}&quot;,${thrift.groupid}.protocol;uses:=&quot;${thrift.groupid}.transport,${thrift.groupid},${thrift.groupid}.scheme&quot;;version=&quot;${version}&quot;,${thrift.groupid}.server;uses:=&quot;${thrift.groupid}.transport,${thrift.groupid}.protocol,${thrift.groupid},org.slf4j,javax.servlet,javax.servlet.http&quot;;version=&quot;${version}&quot;,${thrift.groupid}.transport;uses:=&quot;${thrift.groupid}.protocol,${thrift.groupid},org.apache.http.client,org.apache.http.params,org.apache.http.entity,org.apache.http.client.methods,org.apache.http,org.slf4j,javax.net.ssl,javax.net,javax.security.sasl,javax.security.auth.callback&quot;;version=&quot;${version}&quot;,${thrift.groupid};uses:=&quot;${thrift.groupid}.protocol,${thrift.groupid}.async,${thrift.groupid}.server,${thrift.groupid}.transport,org.slf4j,org.apache.log4j,${thrift.groupid}.scheme&quot;;version=&quot;${version}&quot;,${thrift.groupid}.meta_data;uses:=&quot;${thrift.groupid}&quot;;version=&quot;${version}&quot;,${thrift.groupid}.scheme;uses:=&quot;${thrift.groupid}.protocol,${thrift.groupid}&quot;;version=&quot;${version}&quot;"/>
-       <attribute name="Import-Package" value="javax.net,javax.net.ssl,javax.security.auth.callback,javax.security.sasl,javax.servlet;resolution:=optional,javax.servlet.http;resolution:=optional,org.slf4j;resolution:=optional;version=&quot;[1.4,2)&quot;,org.apache.http.client;resolution:=optional,org.apache.http.params;resolution:=optional,org.apache.http.entity;resolution:=optional,org.apache.http.client.methods;resolution:=optional,org.apache.http;resolution:=optional"/>
-      </manifest>
-      <fileset dir="${build.dir}">
-        <include name="org/apache/thrift/**/*.class"/>
-        <include name="META-INF/*.txt"/>
-      </fileset>
-    </jar>
-  </target>
-
-  <target name="pack.src">
-    <jar jarfile="${source.jar.file}">
-      <fileset dir="${src}">
-        <include name="**/*.java"/>
-      </fileset>
-    </jar>
-  </target>
-
-  <target name="install" depends="dist,javadoc">
-    <copy todir="${install.path}">
-      <fileset dir="${build.dir}" includes="*.jar"/>
-      <fileset dir="${build.lib.dir}" includes="*.jar"/>
-    </copy>
-    <copy todir="${install.javadoc.path}">
-      <fileset dir="${javadoc.dir}" includes="**/*"/>
-    </copy>
-  </target>
-
-  <target name="clean">
-    <delete dir="${build.dir}"/>
-    <delete dir="${gen}"/>
-    <delete dir="${genbean}"/>
-    <delete dir="${genreuse}"/>
-    <delete dir="${genfullcamel}"/>
-  </target>
-
-  <target name="optional-generate" unless="no-gen-thrift">
-    <antcall target="generate">
-    </antcall>
-  </target>
-
-  <target name="compile-test" description="Build the test suite classes" depends="optional-generate,dist">
-    <javac compiler="modern" debug="true" srcdir="${gen}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:deprecation"/>
-      <!--<compilerarg value="-Xlint:unchecked"/>-->
-    </javac>
-    <javac compiler="modern" debug="true" srcdir="${genbean}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:deprecation"/>
-      <!--<compilerarg value="-Xlint:unchecked"/>-->
-    </javac>
-    <javac compiler="modern" debug="true" srcdir="${genreuse}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:deprecation"/>
-      <!--<compilerarg value="-Xlint:unchecked"/>-->
-    </javac>
-    <javac compiler="modern" debug="true" srcdir="${genfullcamel}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:deprecation"/>
-      <!--<compilerarg value="-Xlint:unchecked"/>-->
-    </javac>
-    <javac compiler="modern" debug="true" srcdir="${src.test}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
-      <compilerarg value="-Xlint:deprecation"/>
-      <!--<compilerarg value="-Xlint:unchecked"/>-->
-    </javac>
-    <copy todir="${build.test.dir}">
-      <fileset dir="${src.test}" includes="log4j.properties"/>
-    </copy>
-    <jar jarfile="${test.jar.file}" basedir="${build.test.dir}"/>
-  </target>
-
-  <target name="junit-test" description="Run the JUnit test suite" depends="compile-test">
-    <mkdir dir="${test.log.dir}"/>
-    <junit printsummary="true" showoutput="${test.output}" timeout="${test.timeout}"
-      haltonfailure="true" errorProperty="tests.failed" failureProperty="tests.failed"
-      fork="true" forkmode="perTest" maxmemory="512m"
-    >
-      <sysproperty key="build.test" value="${build.test.dir}"/>
-      <sysproperty key="test.port" value="${test.port}"/>
-      <sysproperty key="javax.net.ssl.trustStore" value="${src.test}/.truststore"/>
-      <sysproperty key="javax.net.ssl.trustStorePassword" value="thrift"/>
-      <sysproperty key="javax.net.ssl.keyStore" value="${src.test}/.keystore"/>
-      <sysproperty key="javax.net.ssl.keyStorePassword" value="thrift"/>
-      <classpath refid="test.classpath"/>
-      <formatter type="${test.junit.output.format}"/>
-      <batchtest todir="${test.log.dir}" unless="testcase">
-        <fileset dir="${test.src.dir}">
-          <include name="**/Test*.java"/>
-          <exclude name="**/TestClient.java"/>
-          <exclude name="**/TestServer.java"/>
-          <exclude name="**/TestNonblockingServer.java"/>
-        </fileset>
-      </batchtest>
-      <batchtest todir="${test.log.dir}" if="testcase">
-        <fileset dir="${test.src.dir}" includes="**/${testcase}.java"/>
-      </batchtest>
-    </junit>
-    <fail if="tests.failed">Tests failed!</fail>
-  </target>
-
-  <target name="deprecated-test" description="Run the non-JUnit test suite" depends="compile-test">
-    <java classname="org.apache.thrift.test.EqualityTest" classpathref="test.classpath" failonerror="true"/>
-    <java classname="org.apache.thrift.test.JavaBeansTest" classpathref="test.classpath" failonerror="true"/>
-  </target>
-
-  <target name="test" description="Run the full test suite" depends="junit-test,deprecated-test"/>
-
-  <target name="testclient" description="Run a test client" depends="compile-test, run-testclient"/>
-  <target name="run-testclient" description="Run a test client">
-    <java classname="org.apache.thrift.test.TestClient"
-      classpathref="test.classpath" failonerror="true" fork="true">
-      <sysproperty key="javax.net.ssl.trustStore" value="${src.test}/.truststore"/>
-      <sysproperty key="javax.net.ssl.trustStorePassword" value="thrift"/>
-      <arg line="${testargs}"/>
-    </java>
-  </target>
-
-  <target name="testserver" description="Run a test server" depends="compile-test, run-testserver"/>
-  <target name="run-testserver" description="Run a test server">
-    <java classname="org.apache.thrift.test.TestServer"
-      classpathref="test.classpath" failonerror="true" fork="true">
-      <sysproperty key="javax.net.ssl.keyStore" value="${src.test}/.keystore"/>
-      <sysproperty key="javax.net.ssl.keyStorePassword" value="thrift"/>
-      <arg line="${testargs}"/>
-    </java>
-  </target>
-
-  <target name="testnonblockingserver" description="Run a test nonblocking server" depends="compile-test, run-testnonblockingserver"/>
-  <target name="run-testnonblockingserver" description="Run a test nonblocking server">
-    <java classname="org.apache.thrift.test.TestNonblockingServer"
-      classpathref="test.classpath" failonerror="true">
-      <arg line="${testargs}"/>
-    </java>
-  </target>
-
-  <target name="generate">
-    <!-- Generate the thrift gen-java source -->
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/ThriftTest.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/JavaTypes.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/DebugProtoTest.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/OptionalRequiredTest.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java:beans,nocamel ${test.thrift.home}/JavaBeansTest.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/ManyOptionals.thrift"/>
-    </exec>
-  	<mkdir dir="${genfullcamel}"/>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java:fullcamel -out ${genfullcamel} ${test.thrift.home}/FullCamelTest.thrift"/>
-    </exec>
-  	<mkdir dir="${genreuse}"/>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java:reuse-objects -out ${genreuse} ${test.thrift.home}/ReuseObjects.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/JavaDeepCopyTest.thrift"/>
-    </exec>
-    <exec executable="${thrift.compiler}" failonerror="true">
-      <arg line="--gen java ${test.thrift.home}/EnumContainersTest.thrift"/>
-    </exec>
-  </target>
-
-  <target name="proxy" if="proxy.enabled">
-    <setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
-      proxyuser="${proxy.user}" proxypassword="${proxy.pass}"/>
-  </target>
-
-  <target name="mvn.ant.tasks.download" depends="setup.init,mvn.ant.tasks.check,proxy" unless="mvn.ant.tasks.found">
-    <get src="${mvn.ant.task.url}/${mvn.ant.task.jar}" dest="${build.tools.dir}/${mvn.ant.task.jar}" usetimestamp="true"/>
-  </target>
-
-  <target name="mvn.ant.tasks.check">
-    <condition property="mvn.ant.tasks.found">
-      <typefound uri="antlib:org.apache.maven.artifact.ant" name="artifact"/>
-    </condition>
-  </target>
-
-  <target name="mvn.init" depends="mvn.ant.tasks.download" unless="mvn.finished">
-    <!-- Download mvn ant tasks, download dependencies, and setup pom file -->
-    <typedef uri="antlib:org.apache.maven.artifact.ant" classpath="${build.tools.dir}/${mvn.ant.task.jar}"/>
-
-    <!-- remote repositories used to download dependencies from -->
-    <artifact:remoteRepository id="central" url="${mvn.repo}"/>
-    <artifact:remoteRepository id="apache" url="${apache.repo}"/>
-
-    <!-- Pom file information -->
-    <artifact:pom id="pom"
-      groupId="${thrift.groupid}"
-      artifactId="${thrift.artifactid}"
-      version="${version}"
-      url="http://thrift.apache.org"
-      name="Apache Thrift"
-      description="Thrift is a software framework for scalable cross-language services development."
-      packaging="pom"
-    >
-      <remoteRepository refid="central"/>
-      <remoteRepository refid="apache"/>
-      <license name="The Apache Software License, Version 2.0" url="${license}"/>
-      <scm connection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
-      developerConnection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
-      url="https://git-wip-us.apache.org/repos/asf?p=thrift.git"
-      />
-      <!-- Thrift Developers -->
-      <developer id="mcslee" name="Mark Slee"/>
-      <developer id="dreiss" name="David Reiss"/>
-      <developer id="aditya" name="Aditya Agarwal"/>
-      <developer id="marck" name="Marc Kwiatkowski"/>
-      <developer id="jwang" name="James Wang"/>
-      <developer id="cpiro" name="Chris Piro"/>
-      <developer id="bmaurer" name="Ben Maurer"/>
-      <developer id="kclark" name="Kevin Clark"/>
-      <developer id="jake" name="Jake Luciani"/>
-      <developer id="bryanduxbury" name="Bryan Duxbury"/>
-      <developer id="esteve" name="Esteve Fernandez"/>
-      <developer id="todd" name="Todd Lipcon"/>
-      <developer id="geechorama" name="Andrew McGeachie"/>
-      <developer id="molinaro" name="Anthony Molinaro"/>
-      <developer id="roger" name="Roger Meier"/>
-      <developer id="jfarrell" name="Jake Farrell"/>
-      <developer id="jensg" name="Jens Geyer"/>
-      <developer id="carl" name="Carl Yeksigian"/>
-
-      <!-- Thrift dependencies list -->
-      <dependency groupId="org.slf4j" artifactId="slf4j-api" version="${slf4j.version}"/>
-      <dependency groupId="javax.servlet" artifactId="servlet-api" version="${servlet.version}" scope="provided"/>
-      <dependency groupId="org.apache.httpcomponents" artifactId="httpclient" version="${httpclient.version}"/>
-      <dependency groupId="org.apache.httpcomponents" artifactId="httpcore" version="${httpcore.version}"/>
-    </artifact:pom>
-
-    <!-- Generate the pom file -->
-    <artifact:writepom pomRefId="pom" file="${pom.xml}"/>
-
-    <!-- Download the dependencies -->
-    <artifact:dependencies filesetId="build-dependency-jars" pomRefId="pom"/>
-
-    <!-- Copy the dependencies to the build/lib dir -->
-    <copy todir="${build.dir}/lib">
-      <fileset refid="build-dependency-jars"/>
-      <mapper type="flatten"/>
-    </copy>
-
-    <!-- Dependencies needed for testing -->
-    <artifact:dependencies filesetId="test-dependency-jars" useScope="runtime">
-      <dependency groupId="org.slf4j" artifactId="slf4j-log4j12" version="${slf4j.version}"/>
-      <dependency groupId="junit" artifactId="junit" version="4.4"/>
-      <dependency groupId="org.mockito" artifactId="mockito-all" version="1.9.5"/>
-    </artifact:dependencies>
-
-    <!-- Copy the test dependencies to the build/lib dir -->
-    <copy todir="${build.dir}/lib">
-      <fileset refid="test-dependency-jars"/>
-      <mapper type="flatten"/>
-    </copy>
-
-    <property name="mvn.finished" value="true"/>
-  </target>
-
-  <macrodef name="signAndDeploy">
-    <!-- Sign and deploy jars to apache repo -->
-    <attribute name="file"/>
-    <attribute name="classifier" default=""/>
-    <attribute name="packaging" default="jar"/>
-    <attribute name="pom" default=""/>
-    <sequential>
-      <artifact:mvn fork="true">
-        <arg value="org.apache.maven.plugins:maven-gpg-plugin:1.6:sign-and-deploy-file"/>
-        <arg value="-DrepositoryId=${maven-repository-id}"/>
-        <arg value="-Durl=${maven-repository-url}"/>
-        <arg value="-DpomFile=@{pom}"/>
-        <arg value="-Dfile=@{file}"/>
-        <arg value="-Dclassifier=@{classifier}"/>
-        <arg value="-Dpackaging=@{packaging}"/>
-        <arg value="-Pgpg"/>
-      </artifact:mvn>
-    </sequential>
-  </macrodef>
-
-  <target name="publish" depends="clean,init,test,dist,javadoc,pack.src">
-    <!-- Compile, package, test and then send release to apache maven repo -->
-    <!-- run with: ant -Drelease=true publish-->
-    <signAndDeploy file="${pom.xml}" packaging="pom" classifier="" pom="${pom.xml}"/>
-    <signAndDeploy file="${jar.file}" classifier="" pom="${pom.xml}"/>
-    <signAndDeploy file="${javadoc.jar.file}" classifier="javadoc" pom="${pom.xml}"/>
-    <signAndDeploy file="${source.jar.file}" classifier="sources" pom="${pom.xml}"/>
-  </target>
-</project>
diff --git a/lib/java/code_quality_tools/findbugs-filter.xml b/lib/java/code_quality_tools/findbugs-filter.xml
new file mode 100644
index 0000000..8a93b0a
--- /dev/null
+++ b/lib/java/code_quality_tools/findbugs-filter.xml
@@ -0,0 +1,51 @@
+<FindBugsFilter>
+    <!--
+        This file controls filtering some of the more obnoxious findbugs reports.
+        Some may be worthy of examination and resolution, others are too nit-picky.
+    -->
+    <Match>
+        <Or>
+            <!-- Filter the missing serialVersionUID errors -->
+            <Bug code="SnVI" />
+            <!-- Filter Malicious code vulnerability Warnings -->
+            <Bug code="EI,EI2" />
+            <!-- Filter Unchecked/unconfirmed cast -->
+            <Bug code="BC" />
+            <!-- Filter Should return a zero length array rather than null? -->
+            <Bug code="PZLA" />
+            <!-- Filter Redundant nullcheck -->
+            <Bug code="RCN" />
+            <!-- Filter Exception is caught when Exception is not thrown -->
+            <Bug code="REC" />
+            <!-- Filter Switch statement found where default case is missing -->
+            <Bug code="SF" />
+            <!-- Filter Unread public/protected field -->
+            <Bug code="UrF" />
+            <!-- Filter Field not initialized in constructor and dereferenced -->
+            <Bug code="UwF" />
+        </Or>
+    </Match>
+     <Match>
+        <!-- Filter method invokes System.exit(...), which shuts down the entire virtual machine -->
+        <Class name="org.apache.thrift.transport.TFileTransport" />
+        <Method name="printUsage" />
+        <Bug code="Dm" />
+     </Match>
+     <Match>
+        <!-- Filter method might ignore java.lang.Exception -->
+       <Class name="org.apache.thrift.transport.TSimpleFileTransport" />
+       <Method name="close" />
+       <Bug code="DE" />
+     </Match>
+     <Match>
+        <!-- Filter method might ignore java.lang.Exception -->
+       <Class name="org.apache.thrift.TNonblockingMultiFetchClient$MultiFetch" />
+       <Method name="run" />
+       <Bug code="DE" />
+     </Match>
+     <Match>
+        <!-- Filter Class defines non-transient non-serializable instance field -->
+       <Class name="org.apache.thrift.server.TServlet" />
+       <Bug code="Se" />
+     </Match>
+</FindBugsFilter>
diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties
new file mode 100644
index 0000000..056a96e
--- /dev/null
+++ b/lib/java/gradle.properties
@@ -0,0 +1,33 @@
+# This file is shared currently between this Gradle build and the
+# Ant builds for fd303 and JavaScript. Keep the dotted notation for
+# the properties to minimize the changes in the dependencies.
+thrift.version=1.0.0
+thrift.groupid=org.apache.thrift
+release=true
+
+# Local Install paths
+install.path=/usr/local/lib
+install.javadoc.path=/usr/local/lib
+
+# Test execution properties
+testPort=9090
+
+# Test with Clover Code coverage (disabled by default)
+cloverEnabled=false
+
+# Maven dependency download locations
+mvn.repo=http://repo1.maven.org/maven2
+apache.repo=https://repository.apache.org/content/repositories/releases
+
+# Apache Maven publish
+license=http://www.apache.org/licenses/LICENSE-2.0.txt
+maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2
+maven-repository-id=apache.releases.https
+
+# Dependency versions
+httpclient.version=4.4.1
+httpcore.version=4.4.1
+slf4j.version=1.7.12
+servlet.version=2.5
+junit.version=4.12
+mockito.version=1.9.5
diff --git a/lib/go/thrift/common_test_pre_go17.go b/lib/java/gradle/additionalArtifacts.gradle
similarity index 61%
copy from lib/go/thrift/common_test_pre_go17.go
copy to lib/java/gradle/additionalArtifacts.gradle
index e6d0c4d..201469d 100644
--- a/lib/go/thrift/common_test_pre_go17.go
+++ b/lib/java/gradle/additionalArtifacts.gradle
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,14 +17,24 @@
  * under the License.
  */
 
-package thrift
+// Following Gradle best practices to keep build logic organized
 
-import "golang.org/x/net/context"
+task sourcesJar(type: Jar, group: 'Build') {
+    description = 'Assembles a jar archive containing the main Java sources.'
 
-type mockProcessor struct {
-	ProcessFunc func(in, out TProtocol) (bool, TException)
+    classifier 'sources'
+    from sourceSets.main.allSource
 }
 
-func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	return m.ProcessFunc(in, out)
+task javadocJar(type: Jar, dependsOn: javadoc, group: 'Build') {
+    description = 'Assembles a jar archive containing the JavaDoc.'
+
+    classifier 'javadoc'
+    from javadoc.destinationDir
 }
+
+artifacts {
+    archives sourcesJar
+    archives javadocJar
+}
+
diff --git a/lib/java/gradle/cloverCoverage.gradle b/lib/java/gradle/cloverCoverage.gradle
new file mode 100644
index 0000000..cef0e79
--- /dev/null
+++ b/lib/java/gradle/cloverCoverage.gradle
@@ -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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// Keep this as an optional feature for now, disabled by default
+if (Boolean.parseBoolean(project.cloverEnabled)) {
+    apply plugin: 'com.bmuschko.clover'
+
+    dependencies {
+        clover 'org.openclover:clover:4.2.+'
+    }
+
+    clover {
+
+        testIncludes = ['**/Test*.java']
+        // Exclude the generated test code from code coverage
+        testExcludes = ['thrift/test/Test*.java']
+
+        compiler {
+            encoding = 'UTF-8'
+            debug = true
+        }
+
+        report {
+            html = true
+            pdf = true
+        }
+    }
+
+    build.dependsOn cloverGenerateReport
+}
diff --git a/lib/java/gradle/codeQualityChecks.gradle b/lib/java/gradle/codeQualityChecks.gradle
new file mode 100644
index 0000000..1ff1c29
--- /dev/null
+++ b/lib/java/gradle/codeQualityChecks.gradle
@@ -0,0 +1,39 @@
+
+// =================================================================
+// Configure the Gradle code quality plugins here.
+//
+
+apply plugin: 'findbugs'
+
+findbugs {
+    ignoreFailures = true
+    toolVersion = '3.0.1'
+    sourceSets = [ sourceSets.main ]
+    effort = 'max'
+    reportLevel = 'low'
+    excludeFilter = file('code_quality_tools/findbugs-filter.xml')
+}
+
+tasks.withType(FindBugs) {
+    reports {
+        text.enabled = false
+        html.enabled = true
+        xml.enabled = false
+    }
+}
+
+apply plugin: 'pmd'
+
+pmd {
+    ignoreFailures = true
+    toolVersion = '6.0.0'
+    sourceSets = [ sourceSets.main ]
+    ruleSets = [ 'java-basic' ]
+}
+
+tasks.withType(Pmd) {
+    reports {
+        html.enabled = true
+        xml.enabled = false
+    }
+}
diff --git a/lib/java/gradle/environment.gradle b/lib/java/gradle/environment.gradle
new file mode 100644
index 0000000..9b7eb1e
--- /dev/null
+++ b/lib/java/gradle/environment.gradle
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// Override the build directory if CMake is used (allows for out-of-tree-builds)
+if (hasProperty('build.dir')) {
+    buildDir = file(property('build.dir'))
+}
+
+// In order to remain compatible with other Ant based builds in the system
+// we convert the gradle.properties into DSL friendly camelCased properties
+ext.installPath = property('install.path')
+ext.installJavadocPath = property('install.javadoc.path')
+
+ext.thriftRoot = file('../..')
+
+if (hasProperty('thrift.compiler')) {
+    ext.thriftCompiler = property('thrift.compiler')
+} else {
+    ext.thriftCompiler = "$thriftRoot/compiler/cpp/thrift"
+}
+
+ext.mvnRepo = property('mvn.repo')
+ext.apacheRepo = property('apache.repo')
+ext.mavenRepositoryUrl = property('maven-repository-url')
+
+// Versions used in this project
+ext.httpclientVersion = property('httpclient.version')
+ext.httpcoreVersion = property('httpcore.version')
+ext.servletVersion = property('servlet.version')
+ext.slf4jVersion = property('slf4j.version')
+ext.junitVersion = property('junit.version')
+ext.mockitoVersion = property('mockito.version')
+
+// In this section you declare where to find the dependencies of your project
+repositories {
+    maven {
+        name 'Maven Central Repository'
+        url mvnRepo
+    }
+    maven {
+        name 'Apache Maven Repository'
+        url apacheRepo
+    }
+}
+
+dependencies {
+    compile "org.slf4j:slf4j-api:${slf4jVersion}"
+    compile "org.apache.httpcomponents:httpclient:${httpclientVersion}"
+    compile "org.apache.httpcomponents:httpcore:${httpcoreVersion}"
+    compile "javax.servlet:servlet-api:${servletVersion}"
+
+    testCompile "junit:junit:${junitVersion}"
+    testCompile "org.mockito:mockito-all:${mockitoVersion}"
+    testRuntime "org.slf4j:slf4j-log4j12:${slf4jVersion}"
+}
diff --git a/lib/java/gradle/functionalTests.gradle b/lib/java/gradle/functionalTests.gradle
new file mode 100644
index 0000000..c420d12
--- /dev/null
+++ b/lib/java/gradle/functionalTests.gradle
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// ----------------------------------------------------------------------------
+// Functional testing harness creation. This helps run the cross-check tests.
+// The Makefile precross target invokes the shadowJar task and the tests.json
+// code is changed to call runclient or runserver as needed.
+
+// ----------------------------------------------------------------------------
+// Cross Test sources are separated in their own sourceSet
+//
+sourceSets {
+    crossTest {
+        java {
+            srcDir 'test'
+            include '**/test/TestClient.java'
+            include '**/test/TestServer.java'
+            include '**/test/TestNonblockingServer.java'
+        }
+    }
+}
+
+configurations {
+    crossTestCompile { extendsFrom testCompile }
+    crossTestRuntime { extendsFrom crossTestCompile, testRuntime }
+}
+
+dependencies {
+    crossTestCompile sourceSets.main.output
+    crossTestCompile sourceSets.test.output
+}
+
+// I am using shadow plugin to make a self contained functional test Uber JAR that
+// eliminates startup problems with wrapping the cross-check harness in Gradle.
+// This is used by the runner scripts as the single classpath entry which
+// allows the process to be as lightweight as it can.
+shadowJar {
+    description = 'Assemble a test JAR file for cross-check execution'
+    // make sure the runners are created when this runs
+    dependsOn 'generateRunnerScriptForClient', 'generateRunnerScriptForServer', 'generateRunnerScriptForNonblockingServer'
+
+    baseName = 'functionalTest'
+    destinationDir = file("$buildDir/functionalTestJar")
+    classifier = null
+
+    // We do not need a version number for this internal jar
+    version = null
+
+    // Bundle the complete set of unit test classes including generated code
+    // and the runtime dependencies in one JAR to expedite execution.
+    from sourceSets.test.output
+    from sourceSets.crossTest.output
+    configurations = [project.configurations.testRuntime]
+}
+
+// Common script runner configuration elements
+def scriptExt = ''
+def execExt = ''
+def scriptHead = '#!/bin/bash'
+def args = '$*'
+
+// Although this is marked internal it is an available and stable interface
+if (org.gradle.internal.os.OperatingSystem.current().windows) {
+    scriptExt = '.bat'
+    execExt = '.exe'
+    scriptHead = '@echo off'
+    args = '%*'
+}
+
+// The Java executable to use with the runner scripts
+def javaExe = file("${System.getProperty('java.home')}/bin/java${execExt}").canonicalPath
+// The common Uber jar path
+def jarPath = shadowJar.archivePath.canonicalPath
+def trustStore = file('test/.truststore').canonicalPath
+def keyStore = file('test/.keystore').canonicalPath
+
+task generateRunnerScriptForClient(group: 'Build') {
+    description = 'Generate a runner script for cross-check tests with TestClient'
+
+    def clientFile = file("$buildDir/runclient${scriptExt}")
+
+    def runClientText = """\
+${scriptHead}
+
+"${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.trustStore=$trustStore" -Djavax.net.ssl.trustStorePassword=thrift org.apache.thrift.test.TestClient $args
+"""
+    inputs.property 'runClientText', runClientText
+    outputs.file clientFile
+
+    doLast {
+        clientFile.parentFile.mkdirs()
+        clientFile.text = runClientText
+        clientFile.setExecutable(true, false)
+    }
+}
+
+task generateRunnerScriptForServer(group: 'Build') {
+    description = 'Generate a runner script for cross-check tests with TestServer'
+
+    def serverFile = file("$buildDir/runserver${scriptExt}")
+
+    def runServerText = """\
+${scriptHead}
+
+"${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestServer $args
+"""
+
+    inputs.property 'runServerText', runServerText
+    outputs.file serverFile
+
+    doLast {
+        serverFile.parentFile.mkdirs()
+        serverFile.text = runServerText
+        serverFile.setExecutable(true, false)
+    }
+}
+
+task generateRunnerScriptForNonblockingServer(group: 'Build') {
+    description = 'Generate a runner script for cross-check tests with TestNonblockingServer'
+
+    def serverFile = file("$buildDir/runnonblockingserver${scriptExt}")
+
+    def runServerText = """\
+${scriptHead}
+
+"${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestNonblockingServer $args
+"""
+
+    inputs.property 'runServerText', runServerText
+    outputs.file serverFile
+
+    doLast {
+        serverFile.parentFile.mkdirs()
+        serverFile.text = runServerText
+        serverFile.setExecutable(true, false)
+    }
+}
diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle
new file mode 100644
index 0000000..2b53739
--- /dev/null
+++ b/lib/java/gradle/generateTestThrift.gradle
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// Generated code locations for Unit tests
+ext.genSrc = file("$buildDir/gen-java")
+ext.genBeanSrc = file("$buildDir/gen-javabean")
+ext.genReuseSrc = file("$buildDir/gen-javareuse")
+ext.genFullCamelSrc = file("$buildDir/gen-fullcamel")
+ext.genUnsafeSrc = file("$buildDir/gen-unsafe")
+
+// Add the generated code directories to the test source set
+sourceSets {
+    test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc, genUnsafeSrc
+}
+
+// ----------------------------------------------------------------------------
+// Code generation for Unit Testing
+
+// A callable closure to make this easier
+ext.thriftCompile = { Task task, String thriftFileName, String generator = 'java', File outputDir = genSrc ->
+    def thriftFile = file("$thriftRoot/test/$thriftFileName")
+    assert thriftFile.exists()
+
+    task.inputs.file thriftFile
+    task.outputs.dir outputDir
+
+    task.doLast {
+        outputDir.mkdirs()
+        def result = exec {
+            executable file(thriftCompiler)
+            args '--gen', generator
+            args '-out', outputDir
+            args thriftFile
+            standardOutput = task.outputBuffer
+            errorOutput = task.outputBuffer
+            ignoreExitValue = true
+        }
+        if (result.exitValue != 0) {
+            // Only show the Thrift compiler output on failures, cuts down on noise!
+            println task.outputBuffer.toString()
+            result.rethrowFailure()
+        }
+    }
+}
+
+task generate(group: 'Build') {
+    description = 'Generate all unit test Thrift sources'
+    compileTestJava.dependsOn it
+}
+
+task generateJava(group: 'Build') {
+    description = 'Generate the thrift gen-java source'
+    generate.dependsOn it
+
+    ext.outputBuffer = new ByteArrayOutputStream()
+
+    thriftCompile(it, 'ThriftTest.thrift')
+    thriftCompile(it, 'JavaTypes.thrift')
+    thriftCompile(it, 'DebugProtoTest.thrift')
+    thriftCompile(it, 'DoubleConstantsTest.thrift')
+    thriftCompile(it, 'OptionalRequiredTest.thrift')
+    thriftCompile(it, 'ManyOptionals.thrift')
+    thriftCompile(it, 'JavaDeepCopyTest.thrift')
+    thriftCompile(it, 'EnumContainersTest.thrift')
+}
+
+task generateBeanJava(group: 'Build') {
+    description = 'Generate the thrift gen-javabean source'
+    generate.dependsOn it
+
+    ext.outputBuffer = new ByteArrayOutputStream()
+
+    thriftCompile(it, 'JavaBeansTest.thrift', 'java:beans,nocamel', genBeanSrc)
+}
+
+task generateReuseJava(group: 'Build') {
+    description = 'Generate the thrift gen-javareuse source'
+    generate.dependsOn it
+
+    ext.outputBuffer = new ByteArrayOutputStream()
+
+    thriftCompile(it, 'FullCamelTest.thrift', 'java:fullcamel', genFullCamelSrc)
+}
+
+task generateFullCamelJava(group: 'Build') {
+    description = 'Generate the thrift gen-fullcamel source'
+    generate.dependsOn it
+
+    ext.outputBuffer = new ByteArrayOutputStream()
+
+    thriftCompile(it, 'ReuseObjects.thrift', 'java:reuse-objects', genReuseSrc)
+}
+
+task generateUnsafeBinariesJava(group: 'Build') {
+    description = 'Generate the thrift gen-unsafebinaries source'
+    generate.dependsOn it
+
+    ext.outputBuffer = new ByteArrayOutputStream()
+
+    thriftCompile(it, 'UnsafeTypes.thrift', 'java:unsafe_binaries', genUnsafeSrc)
+}
diff --git a/lib/java/gradle/publishing.gradle b/lib/java/gradle/publishing.gradle
new file mode 100644
index 0000000..6b04043
--- /dev/null
+++ b/lib/java/gradle/publishing.gradle
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// ----------------------------------------------------------------------------
+// Installation subtasks, not used currently, we use "make install/fast"
+task installDist(type: Copy, group: 'Install') {
+    description = "Copy Thrift JAR and dependencies into $installPath location"
+
+    destinationDir = file(installPath)
+
+    from jar
+    from configurations.compile
+}
+
+task installJavadoc(type: Copy, group: 'Install', dependsOn: javadoc) {
+    description = "Install Thrift JavaDoc into $installJavadocPath location"
+
+    destinationDir = file(installJavadocPath)
+
+    from javadoc.destinationDir
+}
+
+// This is not needed by Gradle builds but the remaining Ant builds seem to
+// need access to the generated test classes for Thrift unit tests so we
+// assist them to use it this way.
+task copyDependencies(type: Copy, group: 'Build') {
+    description = 'Copy runtime dependencies in a common location for other Ant based projects'
+    project.assemble.dependsOn it
+
+    destinationDir = file("$buildDir/deps")
+    from configurations.testRuntime
+    // exclude some very specific unit test dependencies
+    exclude '**/junit*.jar', '**/mockito*.jar', '**/hamcrest*.jar'
+}
+
+// ----------------------------------------------------------------------------
+// Allow this configuration to be shared between install and uploadArchives tasks
+def configurePom(pom) {
+    pom.project {
+        name 'Apache Thrift'
+        description 'Thrift is a software framework for scalable cross-language services development.'
+        packaging 'jar'
+        url 'http://thrift.apache.org'
+
+        scm {
+            url 'https://github.com/apache/thrift.git'
+            connection 'scm:git:https://github.com/apache/thrift.git'
+            developerConnection 'scm:git:https://github.com/apache/thrift.git'
+        }
+
+        licenses {
+            license {
+                name 'The Apache Software License, Version 2.0'
+                url "${project.license}"
+                distribution 'repo'
+            }
+        }
+
+        developers {
+            developer {
+                id 'dev'
+                name 'Apache Thrift Developers'
+                email 'dev@thrift.apache.org'
+            }
+        }
+    }
+
+    pom.whenConfigured {
+        // Fixup the scope for servlet-api to be 'provided' instead of 'compile'
+        dependencies.find { dep -> dep.groupId == 'javax.servlet' && dep.artifactId == 'servlet-api' }.with {
+            // it.optional = true
+            it.scope = 'provided'
+        }
+    }
+}
+
+install {
+    repositories.mavenInstaller {
+        configurePom(pom)
+    }
+}
+
+uploadArchives {
+    dependsOn test // make sure we run unit tests when publishing
+    repositories.mavenDeployer {
+        // signPom will silently do nothing when no signing information is provided
+        beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+        repository(url: project.mavenRepositoryUrl) {
+            if (project.hasProperty('mavenUser') && project.hasProperty('mavenPassword')) {
+                authentication(userName: mavenUser, password: mavenPassword)
+            }
+        }
+        configurePom(pom)
+    }
+}
+
+// Signing configuration, optional, only when release and uploadArchives is activated
+signing {
+    required { !version.endsWith("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
+    sign configurations.archives
+}
diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle
new file mode 100644
index 0000000..8dd0331
--- /dev/null
+++ b/lib/java/gradle/sourceConfiguration.gradle
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// ----------------------------------------------------------------------------
+// source sets for main and test sources
+sourceSets {
+    main {
+        java {
+            srcDir 'src'
+        }
+    }
+    test {
+        java {
+            srcDir 'test'
+            // see functionalTests.gradle for these files
+            exclude '**/test/TestClient.java'
+            exclude '**/test/TestServer.java'
+            exclude '**/test/TestNonblockingServer.java'
+        }
+        resources {
+            srcDir 'test'
+            include 'log4j.properties'
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Compiler configuration details
+
+sourceCompatibility = '1.8'
+targetCompatibility = '1.8'
+
+tasks.withType(JavaCompile) {
+    options.encoding = 'UTF-8'
+    options.debug = true
+    options.deprecation = true
+    // options.compilerArgs.addAll('-Xlint:unchecked')
+}
+
+// ----------------------------------------------------------------------------
+// Jar packaging details
+processResources {
+    into('META-INF') {
+        from "$thriftRoot/LICENSE"
+        from "$thriftRoot/NOTICE"
+        rename('(.+)', '$1.txt')
+    }
+}
+
+jar {
+    project.test.dependsOn it
+    manifest {
+        attributes([
+            "Implementation-Version": "${project.version}",
+            "Bundle-ManifestVersion": "2",
+            "Bundle-SymbolicName": "${project.group}",
+            "Bundle-Name": "Apache Thrift",
+            "Bundle-Version": "${project.version}",
+            "Bundle-Description": "Apache Thrift library",
+            "Bundle-License": "${project.license}",
+            "Bundle-ActivationPolicy": "lazy",
+            "Export-Package": "${project.group}.async;uses:=\"${project.group}.protocol,${project.group}.transport,org.slf4j,${project.group}\";version=\"${version}\",${project.group}.protocol;uses:=\"${project.group}.transport,${project.group},${project.group}.scheme\";version=\"${version}\",${project.group}.server;uses:=\"${project.group}.transport,${project.group}.protocol,${project.group},org.slf4j,javax.servlet,javax.servlet.http\";version=\"${version}\",${project.group}.transport;uses:=\"${project.group}.protocol,${project.group},org.apache.http.client,org.apache.http.params,org.apache.http.entity,org.apache.http.client.methods,org.apache.http,org.slf4j,javax.net.ssl,javax.net,javax.security.sasl,javax.security.auth.callback\";version=\"${version}\",${project.group};uses:=\"${project.group}.protocol,${project.group}.async,${project.group}.server,${project.group}.transport,org.slf4j,org.apache.log4j,${project.group}.scheme\";version=\"${version}\",${project.group}.meta_data;uses:=\"${project.group}\";version=\"${version}\",${project.group}.scheme;uses:=\"${project.group}.protocol,${project.group}\";version=\"${version}\"",
+            "Import-Package": "javax.net,javax.net.ssl,javax.security.auth.callback,javax.security.sasl,javax.servlet;resolution:=optional,javax.servlet.http;resolution:=optional,org.slf4j;resolution:=optional;version=\"[1.4,2)\",org.apache.http.client;resolution:=optional,org.apache.http.params;resolution:=optional,org.apache.http.entity;resolution:=optional,org.apache.http.client.methods;resolution:=optional,org.apache.http;resolution:=optional"
+        ])
+    }
+}
diff --git a/lib/java/gradle/unitTests.gradle b/lib/java/gradle/unitTests.gradle
new file mode 100644
index 0000000..61f2fbd
--- /dev/null
+++ b/lib/java/gradle/unitTests.gradle
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+// Following Gradle best practices to keep build logic organized
+
+// Bundle the test classes in a JAR for other Ant based builds
+task testJar(type: Jar, group: 'Build') {
+    description = 'Assembles a jar archive containing the test classes.'
+    project.test.dependsOn it
+
+    classifier 'test'
+    from sourceSets.test.output
+}
+
+// ----------------------------------------------------------------------------
+// Unit test tasks and configurations
+
+// Help the up to date algorithm to make these tests done
+ext.markTaskDone = { task ->
+    def buildFile = file("$buildDir/${task.name}.flag")
+    task.inputs.files task.classpath
+    task.outputs.file buildFile
+    task.doLast {
+        buildFile.text = 'Passed!'
+    }
+}
+
+task deprecatedEqualityTest(type: JavaExec, group: 'Verification') {
+    description = 'Run the non-JUnit test suite '
+    classpath = sourceSets.test.runtimeClasspath
+    main 'org.apache.thrift.test.EqualityTest'
+    markTaskDone(it)
+}
+
+task deprecatedJavaBeansTest(type: JavaExec, group: 'Verification') {
+    description = 'Run the non-JUnit test suite '
+    classpath = sourceSets.test.runtimeClasspath
+    main 'org.apache.thrift.test.JavaBeansTest'
+    markTaskDone(it)
+}
+
+// Main Unit Test task configuration
+test {
+    description="Run the full test suite"
+    dependsOn deprecatedEqualityTest, deprecatedJavaBeansTest
+
+    // Allow repeating tests even after successful execution
+    if (project.hasProperty('rerunTests')) {
+        outputs.upToDateWhen { false }
+    }
+
+    include '**/Test*.class'
+    exclude '**/Test*\$*.class'
+
+    maxHeapSize = '512m'
+    forkEvery = 1
+
+    systemProperties = [
+        'build.test': "${compileTestJava.destinationDir}",
+        'test.port': "${testPort}",
+        'javax.net.ssl.trustStore': "${projectDir}/test/.truststore",
+        'javax.net.ssl.trustStorePassword': 'thrift',
+        'javax.net.ssl.keyStore': "${projectDir}/test/.keystore",
+        'javax.net.ssl.keyStorePassword': 'thrift'
+    ]
+}
diff --git a/lib/java/gradle/wrapper/gradle-wrapper.jar b/lib/java/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..99340b4
--- /dev/null
+++ b/lib/java/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/lib/java/gradle/wrapper/gradle-wrapper.properties b/lib/java/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..2c2bbe5
--- /dev/null
+++ b/lib/java/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
diff --git a/lib/java/gradlew b/lib/java/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/lib/java/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/lib/java/gradlew.bat b/lib/java/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/lib/java/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/test/php/TestPsr4.php b/lib/java/settings.gradle
similarity index 91%
copy from test/php/TestPsr4.php
copy to lib/java/settings.gradle
index d30bf1c..c9bd8bc 100644
--- a/test/php/TestPsr4.php
+++ b/lib/java/settings.gradle
@@ -17,7 +17,4 @@
  * under the License.
  */
 
-<?php
-$GEN_DIR = 'gen-php-psr4';
-include_once('TestClient.php');
-?>
+rootProject.name = 'libthrift'
diff --git a/lib/java/src/org/apache/thrift/AsyncProcessFunction.java b/lib/java/src/org/apache/thrift/AsyncProcessFunction.java
index 550ebd5..483c8d0 100644
--- a/lib/java/src/org/apache/thrift/AsyncProcessFunction.java
+++ b/lib/java/src/org/apache/thrift/AsyncProcessFunction.java
@@ -20,7 +20,6 @@
 
 import org.apache.thrift.async.AsyncMethodCallback;
 import org.apache.thrift.protocol.TMessage;
-import org.apache.thrift.protocol.TMessageType;
 import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.server.AbstractNonblockingServer;
 
diff --git a/lib/java/src/org/apache/thrift/Option.java b/lib/java/src/org/apache/thrift/Option.java
index db25ec5..d5cd309 100644
--- a/lib/java/src/org/apache/thrift/Option.java
+++ b/lib/java/src/org/apache/thrift/Option.java
@@ -24,6 +24,9 @@
  */
 public abstract class Option<T> {
 
+    @SuppressWarnings("rawtypes")
+    private static final Option NONE = new None();
+
     /**
      * Whether the Option is defined or not
      * @return
@@ -87,7 +90,7 @@
         }
 
         public String toString() {
-            return "Some("+value.toString()+")";
+            return "Some(" + value + ")";
         }
     }
 
@@ -99,9 +102,9 @@
      */
     public static <T> Option<T> fromNullable(T value) {
         if (value != null) {
-            return new Some<T>(value);
+            return some(value);
         } else {
-            return new None<T>();
+            return none();
         }
     }
 
@@ -115,7 +118,8 @@
         return new Some<T>(value);
     }
 
+    @SuppressWarnings("unchecked")
     public static <T> None<T> none() {
-        return new None<T>();
+        return (None<T>) NONE;
     }
 }
\ No newline at end of file
diff --git a/lib/java/src/org/apache/thrift/ProcessFunction.java b/lib/java/src/org/apache/thrift/ProcessFunction.java
index 340e301..e6213df 100644
--- a/lib/java/src/org/apache/thrift/ProcessFunction.java
+++ b/lib/java/src/org/apache/thrift/ProcessFunction.java
@@ -45,6 +45,7 @@
       msgType = TMessageType.EXCEPTION;
     } catch (Exception ex) {
       LOGGER.error("Internal error processing " + getMethodName(), ex);
+      if(rethrowUnhandledExceptions()) throw new RuntimeException(ex.getMessage(), ex);
       if(!isOneway()) {
         result = new TApplicationException(TApplicationException.INTERNAL_ERROR,
             "Internal error processing " + getMethodName());
@@ -71,7 +72,7 @@
     }
   }
 
-  protected boolean handleRuntimeExceptions() {
+  protected boolean rethrowUnhandledExceptions(){
     return false;
   }
 
diff --git a/lib/java/src/org/apache/thrift/TAsyncProcessor.java b/lib/java/src/org/apache/thrift/TAsyncProcessor.java
index 0a069ea..533e74d 100644
--- a/lib/java/src/org/apache/thrift/TAsyncProcessor.java
+++ b/lib/java/src/org/apache/thrift/TAsyncProcessor.java
@@ -18,14 +18,7 @@
  */
 package org.apache.thrift;
 
-import org.apache.thrift.protocol.*;
-
-import org.apache.thrift.server.AbstractNonblockingServer.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.Map;
+import org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer;
 
 public interface TAsyncProcessor {
     /**
diff --git a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java
index 9459c1a..0ab1827 100644
--- a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java
+++ b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java
@@ -54,8 +54,13 @@
         if (fn == null) {
             TProtocolUtil.skip(in, TType.STRUCT);
             in.readMessageEnd();
-            if (!fn.isOneway()) {
-              TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
+
+            TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD,
+                "Invalid method name: '" + msg.name + "'");
+            LOGGER.debug("Invalid method name", x);
+
+            // this means it is a two-way request, so we can send a reply
+            if (msg.type == TMessageType.CALL) {
               out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
               x.write(out);
               out.writeMessageEnd();
@@ -72,8 +77,12 @@
             args.read(in);
         } catch (TProtocolException e) {
             in.readMessageEnd();
+
+            TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR,
+                e.getMessage());
+            LOGGER.debug("Could not retrieve function arguments", x);
+
             if (!fn.isOneway()) {
-              TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
               out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
               x.write(out);
               out.writeMessageEnd();
@@ -93,6 +102,7 @@
         try {
           fn.start(iface, args, resultHandler);
         } catch (Exception e) {
+          LOGGER.debug("Exception handling function", e);
           resultHandler.onError(e);
         }
         return true;
diff --git a/lib/java/src/org/apache/thrift/TBaseHelper.java b/lib/java/src/org/apache/thrift/TBaseHelper.java
index 559df33..6f6c6eb 100644
--- a/lib/java/src/org/apache/thrift/TBaseHelper.java
+++ b/lib/java/src/org/apache/thrift/TBaseHelper.java
@@ -25,10 +25,11 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;
-import java.util.SortedSet;
 import java.util.TreeMap;
-import java.util.TreeSet;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 
 public final class TBaseHelper {
 
@@ -53,57 +54,27 @@
   }
 
   public static int compareTo(boolean a, boolean b) {
-    return Boolean.valueOf(a).compareTo(b);
+    return Boolean.compare(a, b);
   }
 
   public static int compareTo(byte a, byte b) {
-    if (a < b) {
-      return -1;
-    } else if (b < a) {
-      return 1;
-    } else {
-      return 0;
-    }
+    return Byte.compare(a, b);
   }
 
   public static int compareTo(short a, short b) {
-    if (a < b) {
-      return -1;
-    } else if (b < a) {
-      return 1;
-    } else {
-      return 0;
-    }
+    return Short.compare(a,b);
   }
 
   public static int compareTo(int a, int b) {
-    if (a < b) {
-      return -1;
-    } else if (b < a) {
-      return 1;
-    } else {
-      return 0;
-    }
+    return Integer.compare(a, b);
   }
 
   public static int compareTo(long a, long b) {
-    if (a < b) {
-      return -1;
-    } else if (b < a) {
-      return 1;
-    } else {
-      return 0;
-    }
+    return Long.compare(a, b);
   }
 
   public static int compareTo(double a, double b) {
-    if (a < b) {
-      return -1;
-    } else if (b < a) {
-      return 1;
-    } else {
-      return 0;
-    }
+    return Double.compare(a, b);
   }
 
   public static int compareTo(String a, String b) {
@@ -111,17 +82,16 @@
   }
 
   public static int compareTo(byte[] a, byte[] b) {
-    int sizeCompare = compareTo(a.length, b.length);
-    if (sizeCompare != 0) {
-      return sizeCompare;
-    }
-    for (int i = 0; i < a.length; i++) {
-      int byteCompare = compareTo(a[i], b[i]);
-      if (byteCompare != 0) {
-        return byteCompare;
+    int compare = compareTo(a.length, b.length);
+    if (compare == 0) {
+      for (int i = 0; i < a.length; i++) {
+        compare = compareTo(a[i], b[i]);
+        if (compare != 0) {
+          break;
+        }
       }
     }
-    return 0;
+    return compare;
   }
 
   public static int compareTo(Comparable a, Comparable b) {
@@ -129,41 +99,39 @@
   }
 
   public static int compareTo(List a, List b) {
-    int lastComparison = compareTo(a.size(), b.size());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    for (int i = 0; i < a.size(); i++) {
-      lastComparison = comparator.compare(a.get(i), b.get(i));
-      if (lastComparison != 0) {
-        return lastComparison;
+    int compare = compareTo(a.size(), b.size());
+    if (compare == 0) {
+      for (int i = 0; i < a.size(); i++) {
+        compare = comparator.compare(a.get(i), b.get(i));
+        if (compare != 0) {
+          break;
+        }
       }
     }
-    return 0;
+    return compare;
   }
 
   public static int compareTo(Set a, Set b) {
-    int lastComparison = compareTo(a.size(), b.size());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    SortedSet sortedA = new TreeSet(comparator);
-    sortedA.addAll(a);
-    SortedSet sortedB = new TreeSet(comparator);
-    sortedB.addAll(b);
+    int compare = compareTo(a.size(), b.size());
+    if (compare == 0) {
+      ArrayList sortedA = new ArrayList(a);
+      ArrayList sortedB = new ArrayList(b);
 
-    Iterator iterA = sortedA.iterator();
-    Iterator iterB = sortedB.iterator();
+      Collections.sort(sortedA, comparator);
+      Collections.sort(sortedB, comparator);
 
-    // Compare each item.
-    while (iterA.hasNext() && iterB.hasNext()) {
-      lastComparison = comparator.compare(iterA.next(), iterB.next());
-      if (lastComparison != 0) {
-        return lastComparison;
+      Iterator iterA = sortedA.iterator();
+      Iterator iterB = sortedB.iterator();
+
+      // Compare each item.
+      while (iterA.hasNext() && iterB.hasNext()) {
+        compare = comparator.compare(iterA.next(), iterB.next());
+        if (compare != 0) {
+          break;
+        }
       }
     }
-
-    return 0;
+    return compare;
   }
 
   public static int compareTo(Map a, Map b) {
@@ -316,22 +284,14 @@
   }
 
   public static byte[] copyBinary(final byte[] orig) {
-    if (orig == null) {
-      return null;
-    }
-
-    byte[] copy = new byte[orig.length];
-    System.arraycopy(orig, 0, copy, 0, orig.length);
-    return copy;
+    return (orig == null) ? null : Arrays.copyOf(orig, orig.length);
   }
 
   public static int hashCode(long value) {
-    int low = (int) value;
-    int high = (int) (value >>> 32);
-    return high * 127 + low;
+    return Long.hashCode(value);
   }
 
   public static int hashCode(double value) {
-    return hashCode(Double.doubleToRawLongBits(value));
+    return Double.hashCode(value);
   }
 }
diff --git a/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java b/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java
index 1c37ecd..3a2d56c 100644
--- a/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java
+++ b/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java
@@ -20,6 +20,7 @@
 package org.apache.thrift;
 
 import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
 
 /**
  * Class that allows access to the underlying buf without doing deep
@@ -53,4 +54,8 @@
   public int len() {
     return count;
   }
+
+  public String toString(Charset charset) {
+    return new String(buf, 0, count, charset);
+  }
 }
diff --git a/lib/java/src/org/apache/thrift/TDeserializer.java b/lib/java/src/org/apache/thrift/TDeserializer.java
index bf6c97c..d1d3966 100644
--- a/lib/java/src/org/apache/thrift/TDeserializer.java
+++ b/lib/java/src/org/apache/thrift/TDeserializer.java
@@ -251,48 +251,31 @@
     try {
       TField field = locateField(bytes, fieldIdPathFirst, fieldIdPathRest);
       if (field != null) {
-        // if this point is reached, iprot will be positioned at the start of the field.
-        switch(ttype){
+        if (ttype == field.type) {
+          // if this point is reached, iprot will be positioned at the start of
+          // the field
+          switch (ttype) {
           case TType.BOOL:
-            if (field.type == TType.BOOL){
-              return protocol_.readBool();
-            }
-            break;
+            return protocol_.readBool();
           case TType.BYTE:
-            if (field.type == TType.BYTE) {
-              return protocol_.readByte();
-            }
-            break;
+            return protocol_.readByte();
           case TType.DOUBLE:
-            if (field.type == TType.DOUBLE) {
-              return protocol_.readDouble();
-            }
-            break;
+            return protocol_.readDouble();
           case TType.I16:
-            if (field.type == TType.I16) {
-              return protocol_.readI16();
-            }
-            break;
+            return protocol_.readI16();
           case TType.I32:
-            if (field.type == TType.I32) {
-              return protocol_.readI32();
-            }
-            break;
+            return protocol_.readI32();
           case TType.I64:
-            if (field.type == TType.I64) {
-              return protocol_.readI64();
-            }
-            break;
+            return protocol_.readI64();
           case TType.STRING:
-            if (field.type == TType.STRING) {
-              return protocol_.readString();
-            }
-            break;
-          case 100: // hack to differentiate between string and binary
-            if (field.type == TType.STRING) {
-              return protocol_.readBinary();
-            }
-            break;
+            return protocol_.readString();
+          default:
+            return null;
+          }
+        }
+        // hack to differentiate between string and binary
+        if (ttype == 100 && field.type == TType.STRING) {
+          return protocol_.readBinary();
         }
       }
       return null;
@@ -307,11 +290,9 @@
   private TField locateField(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException {
     trans_.reset(bytes);
 
-    TFieldIdEnum[] fieldIdPath= new TFieldIdEnum[fieldIdPathRest.length + 1];
+    TFieldIdEnum[] fieldIdPath = new TFieldIdEnum[fieldIdPathRest.length + 1];
     fieldIdPath[0] = fieldIdPathFirst;
-    for (int i = 0; i < fieldIdPathRest.length; i++){
-      fieldIdPath[i + 1] = fieldIdPathRest[i];
-    }
+    System.arraycopy(fieldIdPathRest, 0, fieldIdPath, 1, fieldIdPathRest.length);
 
     // index into field ID path being currently searched for
     int curPathIndex = 0;
diff --git a/lib/java/src/org/apache/thrift/TEnumHelper.java b/lib/java/src/org/apache/thrift/TEnumHelper.java
index c17d661..fbc7787 100644
--- a/lib/java/src/org/apache/thrift/TEnumHelper.java
+++ b/lib/java/src/org/apache/thrift/TEnumHelper.java
@@ -19,7 +19,6 @@
 
 package org.apache.thrift;
 
-import java.lang.InstantiationException;
 import java.lang.NoSuchMethodException;
 import java.lang.IllegalAccessException;
 import java.lang.reflect.InvocationTargetException;
diff --git a/lib/java/src/org/apache/thrift/TUnion.java b/lib/java/src/org/apache/thrift/TUnion.java
index 13f9c67..1ef11df 100644
--- a/lib/java/src/org/apache/thrift/TUnion.java
+++ b/lib/java/src/org/apache/thrift/TUnion.java
@@ -79,7 +79,7 @@
   }
 
   private static Map deepCopyMap(Map<Object, Object> map) {
-    Map copy = new HashMap();
+    Map copy = new HashMap(map.size());
     for (Map.Entry<Object, Object> entry : map.entrySet()) {
       copy.put(deepCopyObject(entry.getKey()), deepCopyObject(entry.getValue()));
     }
@@ -87,7 +87,7 @@
   }
 
   private static Set deepCopySet(Set set) {
-    Set copy = new HashSet();
+    Set copy = new HashSet(set.size());
     for (Object o : set) {
       copy.add(deepCopyObject(o));
     }
diff --git a/lib/go/thrift/common_test_pre_go17.go b/lib/java/src/org/apache/thrift/annotation/Nullable.java
similarity index 66%
copy from lib/go/thrift/common_test_pre_go17.go
copy to lib/java/src/org/apache/thrift/annotation/Nullable.java
index e6d0c4d..a34b01e 100644
--- a/lib/go/thrift/common_test_pre_go17.go
+++ b/lib/java/src/org/apache/thrift/annotation/Nullable.java
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,14 +17,17 @@
  * under the License.
  */
 
-package thrift
+package org.apache.thrift.annotation;
 
-import "golang.org/x/net/context"
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
-type mockProcessor struct {
-	ProcessFunc func(in, out TProtocol) (bool, TException)
-}
+/**
+ * Annotation indicating a field, method return, or method parameter may be {@code null}.
+ * We package our own annotation to avoid a mandatory third-party dependency.
+ */
+@Retention(RetentionPolicy.CLASS)
+public @interface Nullable {
 
-func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	return m.ProcessFunc(in, out)
 }
diff --git a/lib/java/src/org/apache/thrift/ShortStack.java b/lib/java/src/org/apache/thrift/protocol/ShortStack.java
similarity index 74%
rename from lib/java/src/org/apache/thrift/ShortStack.java
rename to lib/java/src/org/apache/thrift/protocol/ShortStack.java
index 4957d1c..9e65930 100644
--- a/lib/java/src/org/apache/thrift/ShortStack.java
+++ b/lib/java/src/org/apache/thrift/protocol/ShortStack.java
@@ -16,45 +16,43 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.thrift;
+package org.apache.thrift.protocol;
+
+import java.util.Arrays;
 
 /**
  * ShortStack is a short-specific Stack implementation written for the express
  * purpose of very fast operations on TCompactProtocol's field id stack. This
  * implementation performs at least 10x faster than java.util.Stack.
  */
-public class ShortStack {
+class ShortStack {
 
   private short[] vector;
-  private int top = -1;
+
+  /** Always points to the next location */
+  private int top = 0;
 
   public ShortStack(int initialCapacity) {
     vector = new short[initialCapacity];
   }
 
   public short pop() {
-    return vector[top--];
+    return vector[--top];
   }
 
   public void push(short pushed) {
-    if (vector.length == top + 1) {
+    if (vector.length == top) {
       grow();
     }
-    vector[++top] = pushed;
+    vector[top++] = pushed;
   }
 
   private void grow() {
-    short[] newVector = new short[vector.length * 2];
-    System.arraycopy(vector, 0, newVector, 0, vector.length);
-    vector = newVector;
-  }
-
-  public short peek() {
-    return vector[top];
+    vector = Arrays.copyOf(vector, vector.length << 1);
   }
 
   public void clear() {
-    top = -1;
+    top = 0;
   }
 
   @Override
@@ -62,18 +60,15 @@
     StringBuilder sb = new StringBuilder();
     sb.append("<ShortStack vector:[");
     for (int i = 0; i < vector.length; i++) {
+      boolean isTop = (i == (top - 1));
+      short value = vector[i];
       if (i != 0) {
-        sb.append(" ");
+        sb.append(' ');
       }
-
-      if (i == top) {
-        sb.append(">>");
-      }
-
-      sb.append(vector[i]);
-
-      if (i == top) {
-        sb.append("<<");
+      if (isTop) {
+        sb.append(">>").append(value).append("<<");
+      } else {
+        sb.append(value);
       }
     }
     sb.append("]>");
diff --git a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java
index aaa1fd8..7924e2f 100644
--- a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java
@@ -19,8 +19,8 @@
 
 package org.apache.thrift.protocol;
 
-import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransport;
@@ -110,6 +110,7 @@
     strictWrite_ = strictWrite;
   }
 
+  @Override
   public void writeMessageBegin(TMessage message) throws TException {
     if (strictWrite_) {
       int version = VERSION_1 | message.type;
@@ -123,60 +124,76 @@
     }
   }
 
-  public void writeMessageEnd() {}
+  @Override
+  public void writeMessageEnd() throws TException {}
 
-  public void writeStructBegin(TStruct struct) {}
+  @Override
+  public void writeStructBegin(TStruct struct) throws TException {}
 
-  public void writeStructEnd() {}
+  @Override
+  public void writeStructEnd() throws TException {}
 
+  @Override
   public void writeFieldBegin(TField field) throws TException {
     writeByte(field.type);
     writeI16(field.id);
   }
 
-  public void writeFieldEnd() {}
+  @Override
+  public void writeFieldEnd() throws TException {}
 
+  @Override
   public void writeFieldStop() throws TException {
     writeByte(TType.STOP);
   }
 
+  @Override
   public void writeMapBegin(TMap map) throws TException {
     writeByte(map.keyType);
     writeByte(map.valueType);
     writeI32(map.size);
   }
 
-  public void writeMapEnd() {}
+  @Override
+  public void writeMapEnd() throws TException {}
 
+  @Override
   public void writeListBegin(TList list) throws TException {
     writeByte(list.elemType);
     writeI32(list.size);
   }
 
-  public void writeListEnd() {}
+  @Override
+  public void writeListEnd() throws TException {}
 
+  @Override
   public void writeSetBegin(TSet set) throws TException {
     writeByte(set.elemType);
     writeI32(set.size);
   }
 
-  public void writeSetEnd() {}
+  @Override
+  public void writeSetEnd() throws TException {}
 
+  @Override
   public void writeBool(boolean b) throws TException {
     writeByte(b ? (byte)1 : (byte)0);
   }
 
+  @Override
   public void writeByte(byte b) throws TException {
     inoutTemp[0] = b;
     trans_.write(inoutTemp, 0, 1);
   }
 
+  @Override
   public void writeI16(short i16) throws TException {
     inoutTemp[0] = (byte)(0xff & (i16 >> 8));
     inoutTemp[1] = (byte)(0xff & (i16));
     trans_.write(inoutTemp, 0, 2);
   }
 
+  @Override
   public void writeI32(int i32) throws TException {
     inoutTemp[0] = (byte)(0xff & (i32 >> 24));
     inoutTemp[1] = (byte)(0xff & (i32 >> 16));
@@ -185,6 +202,7 @@
     trans_.write(inoutTemp, 0, 4);
   }
 
+  @Override
   public void writeI64(long i64) throws TException {
     inoutTemp[0] = (byte)(0xff & (i64 >> 56));
     inoutTemp[1] = (byte)(0xff & (i64 >> 48));
@@ -197,20 +215,19 @@
     trans_.write(inoutTemp, 0, 8);
   }
 
+  @Override
   public void writeDouble(double dub) throws TException {
     writeI64(Double.doubleToLongBits(dub));
   }
 
+  @Override
   public void writeString(String str) throws TException {
-    try {
-      byte[] dat = str.getBytes("UTF-8");
-      writeI32(dat.length);
-      trans_.write(dat, 0, dat.length);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] dat = str.getBytes(StandardCharsets.UTF_8);
+    writeI32(dat.length);
+    trans_.write(dat, 0, dat.length);
   }
 
+  @Override
   public void writeBinary(ByteBuffer bin) throws TException {
     int length = bin.limit() - bin.position();
     writeI32(length);
@@ -221,6 +238,7 @@
    * Reading methods.
    */
 
+  @Override
   public TMessage readMessageBegin() throws TException {
     int size = readI32();
     if (size < 0) {
@@ -237,50 +255,63 @@
     }
   }
 
-  public void readMessageEnd() {}
+  @Override
+  public void readMessageEnd() throws TException {}
 
-  public TStruct readStructBegin() {
+  @Override
+  public TStruct readStructBegin() throws TException {
     return ANONYMOUS_STRUCT;
   }
 
-  public void readStructEnd() {}
+  @Override
+  public void readStructEnd() throws TException {}
 
+  @Override
   public TField readFieldBegin() throws TException {
     byte type = readByte();
     short id = type == TType.STOP ? 0 : readI16();
     return new TField("", type, id);
   }
 
-  public void readFieldEnd() {}
+  @Override
+  public void readFieldEnd() throws TException {}
 
+  @Override
   public TMap readMapBegin() throws TException {
     TMap map = new TMap(readByte(), readByte(), readI32());
     checkContainerReadLength(map.size);
     return map;
   }
 
-  public void readMapEnd() {}
+  @Override
+  public void readMapEnd() throws TException {}
 
+  @Override
   public TList readListBegin() throws TException {
     TList list = new TList(readByte(), readI32());
     checkContainerReadLength(list.size);
     return list;
   }
 
-  public void readListEnd() {}
+  @Override
+  public void readListEnd() throws TException {}
 
+  @Override
   public TSet readSetBegin() throws TException {
     TSet set = new TSet(readByte(), readI32());
     checkContainerReadLength(set.size);
     return set;
   }
 
-  public void readSetEnd() {}
+  @Override
+  public void readSetEnd() throws TException {}
 
+  @Override
   public boolean readBool() throws TException {
     return (readByte() == 1);
   }
 
+  @Override
   public byte readByte() throws TException {
     if (trans_.getBytesRemainingInBuffer() >= 1) {
       byte b = trans_.getBuffer()[trans_.getBufferPosition()];
@@ -291,6 +322,7 @@
     return inoutTemp[0];
   }
 
+  @Override
   public short readI16() throws TException {
     byte[] buf = inoutTemp;
     int off = 0;
@@ -309,6 +341,7 @@
        ((buf[off+1] & 0xff)));
   }
 
+  @Override
   public int readI32() throws TException {
     byte[] buf = inoutTemp;
     int off = 0;
@@ -327,6 +360,7 @@
       ((buf[off+3] & 0xff));
   }
 
+  @Override
   public long readI64() throws TException {
     byte[] buf = inoutTemp;
     int off = 0;
@@ -350,23 +384,22 @@
       ((long)(buf[off+7] & 0xff));
   }
 
+  @Override
   public double readDouble() throws TException {
     return Double.longBitsToDouble(readI64());
   }
 
+  @Override
   public String readString() throws TException {
     int size = readI32();
 
     checkStringReadLength(size);
 
     if (trans_.getBytesRemainingInBuffer() >= size) {
-      try {
-        String s = new String(trans_.getBuffer(), trans_.getBufferPosition(), size, "UTF-8");
-        trans_.consumeBuffer(size);
-        return s;
-      } catch (UnsupportedEncodingException e) {
-        throw new TException("JVM DOES NOT SUPPORT UTF-8");
-      }
+      String s = new String(trans_.getBuffer(), trans_.getBufferPosition(),
+          size, StandardCharsets.UTF_8);
+      trans_.consumeBuffer(size);
+      return s;
     }
 
     return readStringBody(size);
@@ -374,15 +407,12 @@
 
   public String readStringBody(int size) throws TException {
     checkStringReadLength(size);
-    try {
-      byte[] buf = new byte[size];
-      trans_.readAll(buf, 0, size);
-      return new String(buf, "UTF-8");
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] buf = new byte[size];
+    trans_.readAll(buf, 0, size);
+    return new String(buf, StandardCharsets.UTF_8);
   }
 
+  @Override
   public ByteBuffer readBinary() throws TException {
     int size = readI32();
 
diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
index 56c349a..ee05869 100644
--- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java
@@ -22,8 +22,8 @@
 
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 
-import org.apache.thrift.ShortStack;
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransport;
 
@@ -202,6 +202,7 @@
    * Write a message header to the wire. Compact Protocol messages contain the
    * protocol version so we can migrate forwards in the future if need be.
    */
+  @Override
   public void writeMessageBegin(TMessage message) throws TException {
     writeByteDirect(PROTOCOL_ID);
     writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
@@ -214,6 +215,7 @@
    * use it as an opportunity to put special placeholder markers on the field
    * stack so we can get the field id deltas correct.
    */
+  @Override
   public void writeStructBegin(TStruct struct) throws TException {
     lastField_.push(lastFieldId_);
     lastFieldId_ = 0;
@@ -359,12 +361,8 @@
    * Write a string to the wire with a varint size preceding.
    */
   public void writeString(String str) throws TException {
-    try {
-      byte[] bytes = str.getBytes("UTF-8");
-      writeBinary(bytes, 0, bytes.length);
-    } catch (UnsupportedEncodingException e) {
-      throw new TException("UTF-8 not supported!");
-    }
+    byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
+    writeBinary(bytes, 0, bytes.length);
   }
 
   /**
@@ -680,17 +678,15 @@
       return "";
     }
 
-    try {
-      if (trans_.getBytesRemainingInBuffer() >= length) {
-        String str = new String(trans_.getBuffer(), trans_.getBufferPosition(), length, "UTF-8");
-        trans_.consumeBuffer(length);
-        return str;
-      } else {
-        return new String(readBinary(length), "UTF-8");
-      }
-    } catch (UnsupportedEncodingException e) {
-      throw new TException("UTF-8 not supported!");
+    final String str;
+    if (trans_.getBytesRemainingInBuffer() >= length) {
+      str = new String(trans_.getBuffer(), trans_.getBufferPosition(),
+          length, StandardCharsets.UTF_8);
+      trans_.consumeBuffer(length);
+    } else {
+      str = new String(readBinary(length), StandardCharsets.UTF_8);
     }
+    return str;
   }
 
   /**
diff --git a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
index fd54fdf..d37c493 100644
--- a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java
@@ -20,8 +20,8 @@
 package org.apache.thrift.protocol;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Stack;
 
@@ -418,12 +418,8 @@
     if (escapeNum) {
       trans_.write(QUOTE);
     }
-    try {
-      byte[] buf = str.getBytes("UTF-8");
-      trans_.write(buf);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] buf = str.getBytes(StandardCharsets.UTF_8);
+    trans_.write(buf);
     if (escapeNum) {
       trans_.write(QUOTE);
     }
@@ -453,12 +449,8 @@
     if (escapeNum) {
       trans_.write(QUOTE);
     }
-    try {
-      byte[] b = str.getBytes("UTF-8");
-      trans_.write(b, 0, b.length);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] b = str.getBytes(StandardCharsets.UTF_8);
+    trans_.write(b, 0, b.length);
     if (escapeNum) {
       trans_.write(QUOTE);
     }
@@ -513,12 +505,8 @@
     resetContext(); // THRIFT-3743
     writeJSONArrayStart();
     writeJSONInteger(VERSION);
-    try {
-      byte[] b = message.name.getBytes("UTF-8");
-      writeJSONString(b);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] b = message.name.getBytes(StandardCharsets.UTF_8);
+    writeJSONString(b);
     writeJSONInteger(message.type);
     writeJSONInteger(message.seqid);
   }
@@ -628,12 +616,8 @@
 
   @Override
   public void writeString(String str) throws TException {
-    try {
-      byte[] b = str.getBytes("UTF-8");
-      writeJSONString(b);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] b = str.getBytes(StandardCharsets.UTF_8);
+    writeJSONString(b);
   }
 
   @Override
@@ -684,19 +668,17 @@
               }
 
               codeunits.add((char)cu);
-              arr.write((new String(new int[] { codeunits.get(0), codeunits.get(1) }, 0, 2)).getBytes("UTF-8"));
+              arr.write(
+                  (new String(new int[] { codeunits.get(0), codeunits.get(1) },
+                      0, 2)).getBytes(StandardCharsets.UTF_8));
               codeunits.clear();
             }
             else {
-              arr.write((new String(new int[] { cu }, 0, 1)).getBytes("UTF-8"));
+              arr.write((new String(new int[] { cu }, 0, 1))
+                  .getBytes(StandardCharsets.UTF_8));
             }
             continue;
-          }
-          catch (UnsupportedEncodingException ex) {
-            throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED,
-                "JVM does not support UTF-8");
-          }
-          catch (IOException ex) {
+          } catch (IOException ex) {
             throw new TProtocolException(TProtocolException.INVALID_DATA,
                 "Invalid unicode sequence");
           }
@@ -777,19 +759,14 @@
     context_.read();
     if (reader_.peek() == QUOTE[0]) {
       TByteArrayOutputStream arr = readJSONString(true);
-      try {
-        double dub = Double.valueOf(arr.toString("UTF-8"));
-        if (!context_.escapeNum() && !Double.isNaN(dub) &&
-            !Double.isInfinite(dub)) {
-          // Throw exception -- we should not be in a string in this case
-          throw new TProtocolException(TProtocolException.INVALID_DATA,
-                                       "Numeric data unexpectedly quoted");
-        }
-        return dub;
+      double dub = Double.valueOf(arr.toString(StandardCharsets.UTF_8));
+      if (!context_.escapeNum() && !Double.isNaN(dub)
+          && !Double.isInfinite(dub)) {
+        // Throw exception -- we should not be in a string in this case
+        throw new TProtocolException(TProtocolException.INVALID_DATA,
+            "Numeric data unexpectedly quoted");
       }
-      catch (UnsupportedEncodingException ex) {
-        throw new TException("JVM DOES NOT SUPPORT UTF-8");
-      }
+      return dub;
     }
     else {
       if (context_.escapeNum()) {
@@ -868,13 +845,7 @@
       throw new TProtocolException(TProtocolException.BAD_VERSION,
                                    "Message contained bad version.");
     }
-    String name;
-    try {
-      name = readJSONString(false).toString("UTF-8");
-    }
-    catch (UnsupportedEncodingException ex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    String name = readJSONString(false).toString(StandardCharsets.UTF_8);
     byte type = (byte) readJSONInteger();
     int seqid = (int) readJSONInteger();
     return new TMessage(name, type, seqid);
@@ -991,12 +962,7 @@
 
   @Override
   public String readString() throws TException {
-    try {
-      return readJSONString(false).toString("UTF-8");
-    }
-    catch (UnsupportedEncodingException ex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    return readJSONString(false).toString(StandardCharsets.UTF_8);
   }
 
   @Override
diff --git a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
index b24e421..eb7e23b 100644
--- a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
+++ b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java
@@ -19,8 +19,8 @@
 
 package org.apache.thrift.protocol;
 
-import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Stack;
 
 import org.apache.thrift.TException;
@@ -167,6 +167,7 @@
     super(trans);
   }
 
+  @Override
   public void writeMessageBegin(TMessage message) throws TException {
     resetWriteContext(); // THRIFT-3743
     trans_.write(LBRACKET);
@@ -176,31 +177,38 @@
     writeI32(message.seqid);
   }
 
+  @Override
   public void writeMessageEnd() throws TException {
     popWriteContext();
     trans_.write(RBRACKET);
   }
 
+  @Override
   public void writeStructBegin(TStruct struct) throws TException {
     writeContext_.write();
     trans_.write(LBRACE);
     pushWriteContext(new StructContext());
   }
 
+  @Override
   public void writeStructEnd() throws TException {
     popWriteContext();
     trans_.write(RBRACE);
   }
 
+  @Override
   public void writeFieldBegin(TField field) throws TException {
     // Note that extra type information is omitted in JSON!
     writeString(field.name);
   }
 
-  public void writeFieldEnd() {}
+  @Override
+  public void writeFieldEnd() throws TException {}
 
-  public void writeFieldStop() {}
+  @Override
+  public void writeFieldStop() throws TException {}
 
+  @Override
   public void writeMapBegin(TMap map) throws TException {
     assertContextIsNotMapKey(MAP);
     writeContext_.write();
@@ -209,11 +217,13 @@
     // No metadata!
   }
 
+  @Override
   public void writeMapEnd() throws TException {
     popWriteContext();
     trans_.write(RBRACE);
   }
 
+  @Override
   public void writeListBegin(TList list) throws TException {
     assertContextIsNotMapKey(LIST);
     writeContext_.write();
@@ -222,11 +232,13 @@
     // No metadata!
   }
 
+  @Override
   public void writeListEnd() throws TException {
     popWriteContext();
     trans_.write(RBRACKET);
   }
 
+  @Override
   public void writeSetBegin(TSet set) throws TException {
     assertContextIsNotMapKey(SET);
     writeContext_.write();
@@ -235,23 +247,28 @@
     // No metadata!
   }
 
+  @Override
   public void writeSetEnd() throws TException {
     popWriteContext();
     trans_.write(RBRACKET);
   }
 
+  @Override
   public void writeBool(boolean b) throws TException {
     writeByte(b ? (byte)1 : (byte)0);
   }
 
+  @Override
   public void writeByte(byte b) throws TException {
     writeI32(b);
   }
 
+  @Override
   public void writeI16(short i16) throws TException {
     writeI32(i16);
   }
 
+  @Override
   public void writeI32(int i32) throws TException {
     if(writeContext_.isMapKey()) {
       writeString(Integer.toString(i32));
@@ -262,14 +279,11 @@
   }
 
   public void _writeStringData(String s) throws TException {
-    try {
-      byte[] b = s.getBytes("UTF-8");
-      trans_.write(b);
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    byte[] b = s.getBytes(StandardCharsets.UTF_8);
+    trans_.write(b);
   }
 
+  @Override
   public void writeI64(long i64) throws TException {
     if(writeContext_.isMapKey()) {
       writeString(Long.toString(i64));
@@ -279,6 +293,7 @@
     }
   }
 
+  @Override
   public void writeDouble(double dub) throws TException {
     if(writeContext_.isMapKey()) {
       writeString(Double.toString(dub));
@@ -288,6 +303,7 @@
     }
   }
 
+  @Override
   public void writeString(String str) throws TException {
     writeContext_.write();
     int length = str.length();
@@ -341,90 +357,108 @@
     _writeStringData(escape.toString());
   }
 
+  @Override
   public void writeBinary(ByteBuffer bin) throws TException {
-    try {
-      // TODO(mcslee): Fix this
-      writeString(new String(bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset(), "UTF-8"));
-    } catch (UnsupportedEncodingException uex) {
-      throw new TException("JVM DOES NOT SUPPORT UTF-8");
-    }
+    // TODO(mcslee): Fix this
+    writeString(new String(bin.array(), bin.position() + bin.arrayOffset(),
+        bin.limit() - bin.position() - bin.arrayOffset(),
+        StandardCharsets.UTF_8));
   }
 
   /**
    * Reading methods.
    */
 
+  @Override
   public TMessage readMessageBegin() throws TException {
     // TODO(mcslee): implement
     return EMPTY_MESSAGE;
   }
 
-  public void readMessageEnd() {}
+  @Override
+  public void readMessageEnd() throws TException {}
 
-  public TStruct readStructBegin() {
+  @Override
+  public TStruct readStructBegin() throws TException {
     // TODO(mcslee): implement
     return ANONYMOUS_STRUCT;
   }
 
-  public void readStructEnd() {}
+  @Override
+  public void readStructEnd() throws TException {}
 
+  @Override
   public TField readFieldBegin() throws TException {
     // TODO(mcslee): implement
     return ANONYMOUS_FIELD;
   }
 
-  public void readFieldEnd() {}
+  @Override
+  public void readFieldEnd() throws TException {}
 
+  @Override
   public TMap readMapBegin() throws TException {
     // TODO(mcslee): implement
     return EMPTY_MAP;
   }
 
-  public void readMapEnd() {}
+  @Override
+  public void readMapEnd() throws TException {}
 
+  @Override
   public TList readListBegin() throws TException {
     // TODO(mcslee): implement
     return EMPTY_LIST;
   }
 
-  public void readListEnd() {}
+  @Override
+  public void readListEnd() throws TException {}
 
+  @Override
   public TSet readSetBegin() throws TException {
     // TODO(mcslee): implement
     return EMPTY_SET;
   }
 
-  public void readSetEnd() {}
+  @Override
+  public void readSetEnd() throws TException {}
 
+  @Override
   public boolean readBool() throws TException {
     return (readByte() == 1);
   }
 
+  @Override
   public byte readByte() throws TException {
     // TODO(mcslee): implement
     return 0;
   }
 
+  @Override
   public short readI16() throws TException {
     // TODO(mcslee): implement
     return 0;
   }
 
+  @Override
   public int readI32() throws TException {
     // TODO(mcslee): implement
     return 0;
   }
 
+  @Override
   public long readI64() throws TException {
     // TODO(mcslee): implement
     return 0;
   }
 
+  @Override
   public double readDouble() throws TException {
     // TODO(mcslee): implement
     return 0;
   }
 
+  @Override
   public String readString() throws TException {
     // TODO(mcslee): implement
     return "";
@@ -435,6 +469,7 @@
     return "";
   }
 
+  @Override
   public ByteBuffer readBinary() throws TException {
     // TODO(mcslee): implement
     return ByteBuffer.wrap(new byte[0]);
diff --git a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java
index 5c62b99..8c206e4 100644
--- a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java
+++ b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java
@@ -435,17 +435,23 @@
      * has come in.
      */
     public void changeSelectInterests() {
-      if (state_ == FrameBufferState.AWAITING_REGISTER_WRITE) {
+      switch (state_) {
+      case AWAITING_REGISTER_WRITE:
         // set the OP_WRITE interest
         selectionKey_.interestOps(SelectionKey.OP_WRITE);
         state_ = FrameBufferState.WRITING;
-      } else if (state_ == FrameBufferState.AWAITING_REGISTER_READ) {
+        break;
+      case AWAITING_REGISTER_READ:
         prepareRead();
-      } else if (state_ == FrameBufferState.AWAITING_CLOSE) {
+        break;
+      case AWAITING_CLOSE:
         close();
         selectionKey_.cancel();
-      } else {
-        LOGGER.error("changeSelectInterest was called, but state is invalid (" + state_ + ")");
+        break;
+      default:
+        LOGGER.error(
+            "changeSelectInterest was called, but state is invalid ({})",
+            state_);
       }
     }
 
diff --git a/lib/java/src/org/apache/thrift/server/TExtensibleServlet.java b/lib/java/src/org/apache/thrift/server/TExtensibleServlet.java
index d328dd6..75082c0 100644
--- a/lib/java/src/org/apache/thrift/server/TExtensibleServlet.java
+++ b/lib/java/src/org/apache/thrift/server/TExtensibleServlet.java
@@ -63,7 +63,7 @@
    * Returns the appropriate {@link TProcessor}. This will be called <b>once</b> just
    * after the {@link #init()} method
    * 
-   * @return
+   * @return the appropriate {@link TProcessor}
    */
   protected abstract TProcessor getProcessor();
 
@@ -71,7 +71,7 @@
    * Returns the appropriate in {@link TProtocolFactory}. This will be called
    * <b>once</b> just after the {@link #init()} method
    * 
-   * @return
+   * @return the appropriate in {@link TProtocolFactory}
    */
   protected abstract TProtocolFactory getInProtocolFactory();
 
@@ -79,7 +79,7 @@
    * Returns the appropriate out {@link TProtocolFactory}. This will be called
    * <b>once</b> just after the {@link #init()} method
    * 
-   * @return
+   * @return the appropriate out {@link TProtocolFactory}
    */
   protected abstract TProtocolFactory getOutProtocolFactory();
 
diff --git a/lib/java/src/org/apache/thrift/server/TServer.java b/lib/java/src/org/apache/thrift/server/TServer.java
index 80f4f86..bac06b2 100644
--- a/lib/java/src/org/apache/thrift/server/TServer.java
+++ b/lib/java/src/org/apache/thrift/server/TServer.java
@@ -123,7 +123,7 @@
    */
   protected TProtocolFactory outputProtocolFactory_;
 
-  private boolean isServing;
+  private volatile boolean isServing;
 
   protected TServerEventHandler eventHandler_;
 
diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java
index 90d5e5b..1697ad6 100644
--- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java
+++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java
@@ -145,22 +145,40 @@
                                   executorQueue);
   }
 
-
-  public void serve() {
-    try {
+  protected ExecutorService getExecutorService() {
+    return executorService_;
+  }
+  
+  protected boolean preServe() {
+  	try {
       serverTransport_.listen();
     } catch (TTransportException ttx) {
       LOGGER.error("Error occurred during listening.", ttx);
-      return;
+      return false;
     }
 
     // Run the preServe event
     if (eventHandler_ != null) {
       eventHandler_.preServe();
     }
-
     stopped_ = false;
     setServing(true);
+    
+    return true;
+  }
+
+  public void serve() {
+  	if (!preServe()) {
+  		return;
+  	}
+
+  	execute();
+  	waitForShutdown();
+    
+    setServing(false);
+  }
+  
+  protected void execute() {
     int failureCount = 0;
     while (!stopped_) {
       try {
@@ -213,8 +231,10 @@
         }
       }
     }
-
-    executorService_.shutdown();
+  }
+  
+  protected void waitForShutdown() {
+  	executorService_.shutdown();
 
     // Loop until awaitTermination finally does return without a interrupted
     // exception. If we don't do this, then we'll shut down prematurely. We want
@@ -232,7 +252,6 @@
         now = newnow;
       }
     }
-    setServing(false);
   }
 
   public void stop() {
@@ -292,14 +311,22 @@
               break;
             }
         }
-      } catch (TSaslTransportException ttx) {
-        // Something thats not SASL was in the stream, continue silently
-      } catch (TTransportException ttx) {
-        // Assume the client died and continue silently
       } catch (TException tx) {
         LOGGER.error("Thrift error occurred during processing of message.", tx);
       } catch (Exception x) {
-        LOGGER.error("Error occurred during processing of message.", x);
+        // We'll usually receive RuntimeException types here
+        // Need to unwrap to ascertain real causing exception before we choose to ignore
+        Throwable realCause = x.getCause();
+        // Ignore err-logging all transport-level/type exceptions
+        if ((realCause != null && realCause instanceof TTransportException)
+            || (x instanceof TTransportException)) {
+          LOGGER.debug(
+              "Received TTransportException during processing of message. Ignoring.",
+              x);
+        } else {
+          // Log the exception at error level and continue
+          LOGGER.error("Error occurred during processing of message.", x);
+        }
       } finally {
         if (eventHandler != null) {
           eventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java
index b02905f..fc3aa92 100644
--- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java
+++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java
@@ -18,6 +18,8 @@
  */
 package org.apache.thrift.transport;
 
+import java.util.Arrays;
+
 /**
  * Helper class that wraps a byte[] so that it can expand and be reused. Users
  * should call resizeIfNecessary to make sure the buffer has suitable capacity,
@@ -25,28 +27,24 @@
  * rate slightly faster than the requested capacity with the (untested)
  * objective of avoiding expensive buffer allocations and copies.
  */
-public class AutoExpandingBuffer {
+class AutoExpandingBuffer {
   private byte[] array;
 
-  private final double growthCoefficient;
-
-  public AutoExpandingBuffer(int initialCapacity, double growthCoefficient) {
-    if (growthCoefficient < 1.0) {
-      throw new IllegalArgumentException("Growth coefficient must be >= 1.0");
-    }
-    array = new byte[initialCapacity];
-    this.growthCoefficient = growthCoefficient;
+  public AutoExpandingBuffer(int initialCapacity) {
+    this.array = new byte[initialCapacity];
   }
 
   public void resizeIfNecessary(int size) {
-    if (array.length < size) {
-      byte[] newBuf = new byte[(int)(size * growthCoefficient)];
-      System.arraycopy(array, 0, newBuf, 0, array.length);
-      array = newBuf;
+    final int currentCapacity = this.array.length;
+    if (currentCapacity < size) {
+      // Increase by a factor of 1.5x
+      int growCapacity = currentCapacity + (currentCapacity >> 1);
+      int newCapacity = Math.max(growCapacity, size);
+      this.array = Arrays.copyOf(array, newCapacity);
     }
   }
 
   public byte[] array() {
-    return array;
+    return this.array;
   }
 }
diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java
index 081bc48..a28d254 100644
--- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java
@@ -28,8 +28,8 @@
   private int pos = 0;
   private int limit = 0;
 
-  public AutoExpandingBufferReadTransport(int initialCapacity, double overgrowthCoefficient) {
-    this.buf = new AutoExpandingBuffer(initialCapacity, overgrowthCoefficient);
+  public AutoExpandingBufferReadTransport(int initialCapacity) {
+    this.buf = new AutoExpandingBuffer(initialCapacity);
   }
 
   public void fill(TTransport inTrans, int length) throws TTransportException {
diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java
index 9b35693..ec7e7d4 100644
--- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java
@@ -25,10 +25,29 @@
 
   private final AutoExpandingBuffer buf;
   private int pos;
+  private int res;
 
-  public AutoExpandingBufferWriteTransport(int initialCapacity, double growthCoefficient) {
-    this.buf = new AutoExpandingBuffer(initialCapacity, growthCoefficient);
-    this.pos = 0;
+  /**
+   * Constructor.
+   * @param initialCapacity the initial capacity of the buffer
+   * @param frontReserve space, if any, to reserve at the beginning such
+   *                     that the first write is after this reserve.
+   *                     This allows framed transport to reserve space
+   *                     for the frame buffer length.
+   * @throws IllegalArgumentException if initialCapacity is less than one
+   * @throws IllegalArgumentException if frontReserve is less than zero
+   * @throws IllegalArgumentException if frontReserve is greater than initialCapacity
+   */
+  public AutoExpandingBufferWriteTransport(int initialCapacity, int frontReserve) {
+    if (initialCapacity < 1) {
+      throw new IllegalArgumentException("initialCapacity");
+    }
+    if (frontReserve < 0 || initialCapacity < frontReserve) {
+      throw new IllegalArgumentException("frontReserve");
+    }
+    this.buf = new AutoExpandingBuffer(initialCapacity);
+    this.pos = frontReserve;
+    this.res = frontReserve;
   }
 
   @Override
@@ -56,11 +75,14 @@
     return buf;
   }
 
-  public int getPos() {
+  /**
+   * @return length of the buffer, including any front reserve
+   */
+  public int getLength() {
     return pos;
   }
 
   public void reset() {
-    pos = 0;
+    pos = res;
   }
 }
diff --git a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java
index d265600..a1fd249 100644
--- a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java
@@ -106,8 +106,8 @@
     this.underlying = underlying;
     this.maxLength = maxLength;
     this.initialBufferCapacity = initialBufferCapacity;
-    writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity, 1.5);
-    readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5);
+    readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity);
+    writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity, 4);
   }
 
   @Override
@@ -166,16 +166,19 @@
     readBuffer.consumeBuffer(len);
   }
 
+  /**
+   * Only clears the read buffer!
+   */
   public void clear() {
-    readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5);
+    readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity);
   }
 
   @Override
   public void flush() throws TTransportException {
-    int length = writeBuffer.getPos();
-    TFramedTransport.encodeFrameSize(length, i32buf);
-    underlying.write(i32buf, 0, 4);
-    underlying.write(writeBuffer.getBuf().array(), 0, length);
+    int payloadLength = writeBuffer.getLength() - 4;        
+    byte[] data = writeBuffer.getBuf().array();
+    TFramedTransport.encodeFrameSize(payloadLength, data);
+    underlying.write(data, 0, payloadLength + 4);
     writeBuffer.reset();
     underlying.flush();
   }
diff --git a/lib/java/src/org/apache/thrift/transport/TFileTransport.java b/lib/java/src/org/apache/thrift/transport/TFileTransport.java
index 915fa73..c011c52 100644
--- a/lib/java/src/org/apache/thrift/transport/TFileTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TFileTransport.java
@@ -366,7 +366,7 @@
       currentEvent_ = new Event(new byte [256]);
 
       if(!readOnly_)
-        outputStream_ = new BufferedOutputStream(inputFile_.getOutputStream(), 8192);
+        outputStream_ = new BufferedOutputStream(inputFile_.getOutputStream());
     } catch (IOException iox) {
       throw new TTransportException(TTransportException.NOT_OPEN, iox);
     }
diff --git a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
index fa531ef..a006c3a 100644
--- a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
@@ -66,16 +66,25 @@
   }
 
   /**
+   * Something to fill in the first four bytes of the buffer
+   * to make room for the frame size.  This allows the
+   * implementation to write once instead of twice.
+   */
+  private static final byte[] sizeFiller_ = new byte[] { 0x00, 0x00, 0x00, 0x00 };
+
+  /**
    * Constructor wraps around another transport
    */
   public TFramedTransport(TTransport transport, int maxLength) {
     transport_ = transport;
     maxLength_ = maxLength;
+    writeBuffer_.write(sizeFiller_, 0, 4);
   }
 
   public TFramedTransport(TTransport transport) {
     transport_ = transport;
     maxLength_ = TFramedTransport.DEFAULT_MAX_LENGTH;
+    writeBuffer_.write(sizeFiller_, 0, 4);
   }
 
   public void open() throws TTransportException {
@@ -155,12 +164,12 @@
   @Override
   public void flush() throws TTransportException {
     byte[] buf = writeBuffer_.get();
-    int len = writeBuffer_.len();
+    int len = writeBuffer_.len() - 4;       // account for the prepended frame size
     writeBuffer_.reset();
+    writeBuffer_.write(sizeFiller_, 0, 4);  // make room for the next frame's size data
 
-    encodeFrameSize(len, i32buf);
-    transport_.write(i32buf, 0, 4);
-    transport_.write(buf, 0, len);
+    encodeFrameSize(len, buf);              // this is the frame length without the filler
+    transport_.write(buf, 0, len + 4);      // we have to write the frame size and frame data
     transport_.flush();
   }
 
diff --git a/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java b/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java
index ef5f5c2..b19ac86 100644
--- a/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java
+++ b/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java
@@ -20,7 +20,7 @@
 package org.apache.thrift.transport;
 
 import org.apache.thrift.TByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
 
 /**
  * Memory buffer-based implementation of the TTransport interface.
@@ -30,6 +30,8 @@
    * Create a TMemoryBuffer with an initial buffer size of <i>size</i>. The
    * internal buffer will grow as necessary to accommodate the size of the data
    * being written to it.
+   *
+   * @param size the initial size of the buffer
    */
   public TMemoryBuffer(int size) {
     arr_ = new TByteArrayOutputStream(size);
@@ -69,11 +71,11 @@
   /**
    * Output the contents of the memory buffer as a String, using the supplied
    * encoding
-   * @param enc  the encoding to use
+   * @param charset the encoding to use
    * @return the contents of the memory buffer as a String
    */
-  public String toString(String enc) throws UnsupportedEncodingException {
-    return arr_.toString(enc);
+  public String toString(Charset charset) {
+    return arr_.toString(charset);
   }
 
   public String inspect() {
diff --git a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java
index 9c60ed1..2232a31 100644
--- a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java
+++ b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java
@@ -186,7 +186,11 @@
       if (params.isTrustStoreSet) {
         tmf = TrustManagerFactory.getInstance(params.trustManagerType);
         KeyStore ts = KeyStore.getInstance(params.trustStoreType);
-        in = getStoreAsStream(params.trustStore);
+        if (params.trustStoreStream != null) {
+          in = params.trustStoreStream;
+        } else {
+          in = getStoreAsStream(params.trustStore);
+        }
         ts.load(in,
                 (params.trustPass != null ? params.trustPass.toCharArray() : null));
         tmf.init(ts);
@@ -195,7 +199,11 @@
       if (params.isKeyStoreSet) {
         kmf = KeyManagerFactory.getInstance(params.keyManagerType);
         KeyStore ks = KeyStore.getInstance(params.keyStoreType);
-        is = getStoreAsStream(params.keyStore);
+        if (params.keyStoreStream != null) {
+        	is = params.keyStoreStream;
+        } else {
+        	is = getStoreAsStream(params.keyStore);
+        }
         ks.load(is, params.keyPass.toCharArray());
         kmf.init(ks, params.keyPass.toCharArray());
       }
@@ -273,10 +281,12 @@
   public static class TSSLTransportParameters {
     protected String protocol = "TLS";
     protected String keyStore;
+    protected InputStream keyStoreStream;
     protected String keyPass;
     protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm();
     protected String keyStoreType = "JKS";
     protected String trustStore;
+    protected InputStream trustStoreStream;
     protected String trustPass;
     protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm();
     protected String trustStoreType = "JKS";
@@ -332,7 +342,20 @@
       }
       isKeyStoreSet = true;
     }
-
+    
+    /**
+     * Set the keystore, password, certificate type and the store type
+     *
+     * @param keyStoreStream Keystore content input stream
+     * @param keyPass Keystore password
+     * @param keyManagerType The default is X509
+     * @param keyStoreType The default is JKS
+     */
+    public void setKeyStore(InputStream keyStoreStream, String keyPass, String keyManagerType, String keyStoreType) {
+    	this.keyStoreStream = keyStoreStream;
+    	setKeyStore("", keyPass, keyManagerType, keyStoreType);
+    }
+    
     /**
      * Set the keystore and password
      *
@@ -342,7 +365,17 @@
     public void setKeyStore(String keyStore, String keyPass) {
       setKeyStore(keyStore, keyPass, null, null);
     }
-
+    
+    /**
+     * Set the keystore and password
+     *
+     * @param keyStoreStream Keystore content input stream
+     * @param keyPass Keystore password
+     */
+    public void setKeyStore(InputStream keyStoreStream, String keyPass) {
+      setKeyStore(keyStoreStream, keyPass, null, null);
+    }
+    
     /**
      * Set the truststore, password, certificate type and the store type
      *
@@ -362,6 +395,19 @@
       }
       isTrustStoreSet = true;
     }
+    
+    /**
+     * Set the truststore, password, certificate type and the store type
+     *
+     * @param trustStoreStream Truststore content input stream
+     * @param trustPass Truststore password
+     * @param trustManagerType The default is X509
+     * @param trustStoreType The default is JKS
+     */
+    public void setTrustStore(InputStream trustStoreStream, String trustPass, String trustManagerType, String trustStoreType) {
+      this.trustStoreStream = trustStoreStream;
+      setTrustStore("", trustPass, trustManagerType, trustStoreType);
+    }
 
     /**
      * Set the truststore and password
@@ -372,6 +418,16 @@
     public void setTrustStore(String trustStore, String trustPass) {
       setTrustStore(trustStore, trustPass, null, null);
     }
+    
+    /**
+     * Set the truststore and password
+     *
+     * @param trustStoreStream Truststore content input stream
+     * @param trustPass Truststore password
+     */
+    public void setTrustStore(InputStream trustStoreStream, String trustPass) {
+      setTrustStore(trustStoreStream, trustPass, null, null);
+    }
 
     /**
      * Set if client authentication is required
@@ -380,6 +436,6 @@
      */
     public void requireClientAuth(boolean clientAuth) {
       this.clientAuth = clientAuth;
-    }
-  }
+		}
+	}
 }
diff --git a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java
index 8122289..4b1ca0a 100644
--- a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java
@@ -19,7 +19,7 @@
 
 package org.apache.thrift.transport;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
 import javax.security.auth.callback.CallbackHandler;
@@ -97,12 +97,7 @@
     LOGGER.debug("Sending mechanism name {} and initial response of length {}", mechanism,
         initialResponse.length);
 
-    byte[] mechanismBytes;
-	try {
-		mechanismBytes = mechanism.getBytes("UTF-8");
-	} catch (UnsupportedEncodingException e) {
-		throw new TTransportException(e);
-	}
+    byte[] mechanismBytes = mechanism.getBytes(StandardCharsets.UTF_8);
     sendSaslMessage(NegotiationStatus.START,
                     mechanismBytes);
     // Send initial response
diff --git a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java
index e6c0e3e..39b81ca 100644
--- a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java
@@ -19,8 +19,8 @@
 
 package org.apache.thrift.transport;
 
-import java.io.UnsupportedEncodingException;
 import java.lang.ref.WeakReference;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -31,7 +31,6 @@
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
-import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -132,12 +131,7 @@
     }
 
     // Get the mechanism name.
-    String mechanismName;
-	try {
-		mechanismName = new String(message.payload, "UTF-8");
-    } catch (UnsupportedEncodingException e) {
-        throw new TTransportException("JVM DOES NOT SUPPORT UTF-8");
-      }
+    String mechanismName = new String(message.payload, StandardCharsets.UTF_8);
     TSaslServerDefinition serverDefinition = serverDefinitionMap.get(mechanismName);
     LOGGER.debug("Received mechanism name '{}'", mechanismName);
 
diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java
index a94d9a7..bed3b39 100644
--- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java
@@ -19,7 +19,7 @@
 
 package org.apache.thrift.transport;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -158,9 +158,9 @@
     messageHeader[0] = status.getValue();
     EncodingUtils.encodeBigEndian(payload.length, messageHeader, STATUS_BYTES);
 
-    if (LOGGER.isDebugEnabled())
-      LOGGER.debug(getRole() + ": Writing message with status {} and payload length {}",
-                   status, payload.length);
+    LOGGER.debug("{}: Writing message with status {} and payload length {}",
+        getRole(), status, payload.length);
+
     underlyingTransport.write(messageHeader);
     underlyingTransport.write(payload);
     underlyingTransport.flush();
@@ -194,17 +194,11 @@
     underlyingTransport.readAll(payload, 0, payload.length);
 
     if (status == NegotiationStatus.BAD || status == NegotiationStatus.ERROR) {
-      try {
-        String remoteMessage = new String(payload, "UTF-8");
-        throw new TTransportException("Peer indicated failure: " + remoteMessage);
-      } catch (UnsupportedEncodingException e) {
-        throw new TTransportException(e);
-      }
+      String remoteMessage = new String(payload, StandardCharsets.UTF_8);
+      throw new TTransportException("Peer indicated failure: " + remoteMessage);
     }
-
-    if (LOGGER.isDebugEnabled())
-      LOGGER.debug(getRole() + ": Received message with status {} and payload length {}",
-                   status, payload.length);
+    LOGGER.debug("{}: Received message with status {} and payload length {}",
+        getRole(), status, payload.length);
     return new SaslResponse(status, payload);
   }
 
@@ -224,7 +218,7 @@
    */
   protected TTransportException sendAndThrowMessage(NegotiationStatus status, String message) throws TTransportException {
     try {
-      sendSaslMessage(status, message.getBytes("UTF-8"));
+      sendSaslMessage(status, message.getBytes(StandardCharsets.UTF_8));
     } catch (Exception e) {
       LOGGER.warn("Could not send failure response", e);
       message += "\nAlso, could not send response: " + e.toString();
@@ -287,7 +281,7 @@
         if (message.status == NegotiationStatus.COMPLETE &&
             getRole() == SaslRole.CLIENT) {
           LOGGER.debug("{}: All done!", getRole());
-          break;
+          continue;
         }
 
         sendSaslMessage(sasl.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK,
@@ -295,8 +289,6 @@
       }
       LOGGER.debug("{}: Main negotiation loop complete", getRole());
 
-      assert sasl.isComplete();
-
       // If we're the client, and we're complete, but the server isn't
       // complete yet, we need to wait for its response. This will occur
       // with ANONYMOUS auth, for example, where we send an initial response
diff --git a/lib/java/src/org/apache/thrift/transport/TSocket.java b/lib/java/src/org/apache/thrift/transport/TSocket.java
index 148122f..b20b32b 100644
--- a/lib/java/src/org/apache/thrift/transport/TSocket.java
+++ b/lib/java/src/org/apache/thrift/transport/TSocket.java
@@ -80,8 +80,8 @@
 
     if (isOpen()) {
       try {
-        inputStream_ = new BufferedInputStream(socket_.getInputStream(), 1024);
-        outputStream_ = new BufferedOutputStream(socket_.getOutputStream(), 1024);
+        inputStream_ = new BufferedInputStream(socket_.getInputStream());
+        outputStream_ = new BufferedOutputStream(socket_.getOutputStream());
       } catch (IOException iox) {
         close();
         throw new TTransportException(TTransportException.NOT_OPEN, iox);
@@ -219,8 +219,8 @@
 
     try {
       socket_.connect(new InetSocketAddress(host_, port_), connectTimeout_);
-      inputStream_ = new BufferedInputStream(socket_.getInputStream(), 1024);
-      outputStream_ = new BufferedOutputStream(socket_.getOutputStream(), 1024);
+      inputStream_ = new BufferedInputStream(socket_.getInputStream());
+      outputStream_ = new BufferedOutputStream(socket_.getOutputStream());
     } catch (IOException iox) {
       close();
       throw new TTransportException(TTransportException.NOT_OPEN, iox);
diff --git a/lib/java/test/org/apache/thrift/Fixtures.java b/lib/java/test/org/apache/thrift/Fixtures.java
index 9f28124..61f40a5 100644
--- a/lib/java/test/org/apache/thrift/Fixtures.java
+++ b/lib/java/test/org/apache/thrift/Fixtures.java
@@ -20,6 +20,7 @@
 package org.apache.thrift;
 
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -267,7 +268,7 @@
       oneOfEach.setInteger64((long) 6000 * 1000 * 1000);
       oneOfEach.setDouble_precision(Math.PI);
       oneOfEach.setSome_characters("JSON THIS! \"\1");
-      oneOfEach.setZomg_unicode(new String(kUnicodeBytes, "UTF-8"));
+      oneOfEach.setZomg_unicode(new String(kUnicodeBytes, StandardCharsets.UTF_8));
       oneOfEach.setBase64(ByteBuffer.wrap("base64".getBytes()));
       // byte, i16, and i64 lists are populated by default constructor
 
@@ -277,7 +278,7 @@
       nesting = new Nesting(bonk, oneOfEach);
 
       holyMoley = new HolyMoley();
-      ArrayList big = new ArrayList<OneOfEach>();
+      List<OneOfEach> big = new ArrayList<OneOfEach>();
       big.add(new OneOfEach(oneOfEach));
       big.add(nesting.my_ooe);
       holyMoley.setBig(big);
diff --git a/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java b/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java
new file mode 100644
index 0000000..d691fe3
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+package org.apache.thrift;
+
+import java.util.List;
+import junit.framework.TestCase;
+import static org.junit.Assert.*;
+import org.junit.Test;
+import thrift.test.DoubleConstantsTestConstants;
+
+public class TestRenderedDoubleConstants extends TestCase {
+    private static final double EPSILON = 0.0000001;
+    private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST =
+        "failed to verify a double constant generated by Thrift (expected = %f, got = %f)";
+    private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =
+        "failed to verify a list item by Thrift (expected = %f, got = %f)";
+    private static final String ASSERTION_MESSAGE_FOR_TYPE_CHECKS =
+        "the rendered variable with name %s is not of double type";
+
+    // to make sure lists containing doubles are generated correctly
+    public void testRenderedDoubleList() throws Exception {
+        final double[] EXPECTED_LIST =
+            {1d,-100d,100d,9223372036854775807d,-9223372036854775807d,3.14159265359,1000000.1,-1000000.1,1.7e+308,
+             -1.7e+308,9223372036854775816.43,-9223372036854775816.43};
+        assertEquals(EXPECTED_LIST.length, DoubleConstantsTestConstants.DOUBLE_LIST_TEST.size());
+        for (int i = 0; i < EXPECTED_LIST.length; ++i) {
+            assertEquals(
+                String.format(
+                    ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST,
+                    EXPECTED_LIST[i],
+                    DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i)),
+                EXPECTED_LIST[i], DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i), EPSILON);
+        }
+    }
+
+    // to make sure the variables inside Thrift files are generated correctly
+    public void testRenderedDoubleConstants() throws Exception {
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43;
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST));
+        //assertTrue(
+        //    String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST"),
+        //    Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST));
+        //assertTrue(
+        //    String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST"),
+        //    Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST));
+        assertTrue(
+            String.format(
+                ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST));
+    }
+}
diff --git a/lib/java/test/org/apache/thrift/TestReuse.java b/lib/java/test/org/apache/thrift/TestReuse.java
index db16c74..b44abd0 100644
--- a/lib/java/test/org/apache/thrift/TestReuse.java
+++ b/lib/java/test/org/apache/thrift/TestReuse.java
@@ -21,10 +21,7 @@
 
 import java.util.HashSet;
 
-import junit.framework.TestCase;
-
 import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.protocol.TType;
 
 import thrift.test.Reuse;
 
diff --git a/lib/java/test/org/apache/thrift/TestShortStack.java b/lib/java/test/org/apache/thrift/TestShortStack.java
deleted file mode 100644
index 07831e5..0000000
--- a/lib/java/test/org/apache/thrift/TestShortStack.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.
- */
-package org.apache.thrift;
-
-import java.util.Stack;
-
-import junit.framework.TestCase;
-
-public class TestShortStack extends TestCase {
-  private static final int NUM_TRIALS = 5;
-  private static final int NUM_REPS = 10000000;
-
-  public void testOps() throws Exception {
-    ShortStack s = new ShortStack(10);
-    s.push((short)10);
-    s.push((short)11);
-    s.push((short)12);
-    assertEquals((short)12, s.peek());
-    assertEquals((short)12, s.peek());
-    assertEquals((short)12, s.pop());
-    assertEquals((short)11, s.pop());
-    s.push((short)40);
-    assertEquals((short)40, s.peek());
-    assertEquals((short)40, s.pop());
-    assertEquals((short)10, s.peek());
-    assertEquals((short)10, s.pop());
-    try {
-      s.peek();
-      fail("should have thrown an exception!");
-    } catch (Exception e) {
-      // yay
-    }
-
-    try {
-      s.pop();
-      fail("should have thrown an exception!");
-    } catch (Exception e) {
-      // yay
-    }
-  }
-
-  public void testGrow() throws Exception {
-    ShortStack s = new ShortStack(1);
-    s.push((short)1);
-    s.push((short)1);
-    s.push((short)1);
-    s.push((short)1);
-    s.push((short)1);
-  }
-
-  public static void main(String[] args) throws Exception {
-    for (int trial = 0; trial < NUM_TRIALS; trial++) {
-      long start = System.currentTimeMillis();
-      ShortStack s = new ShortStack(10);
-      for (int rep = 0; rep < NUM_REPS; rep++) {
-        s.push((short)1);
-        s.push((short)11);
-        s.push((short)111);
-        s.pop();
-        s.pop();
-        s.push((short)12);
-        s.push((short)121);
-        s.push((short)1211);
-        s.push((short)12111);
-        s.pop();
-        s.pop();
-        s.pop();
-        s.pop();
-        s.push((short)5);
-        s.pop();
-        s.pop();
-      }
-      long end = System.currentTimeMillis();
-      System.out.println("ShortStack: " + (end-start));
-
-      start = System.currentTimeMillis();
-      Stack<Short> stdStack = new Stack<Short>();
-      for (int rep = 0; rep < NUM_REPS; rep++) {
-        stdStack.push((short)1);
-        stdStack.push((short)11);
-        stdStack.push((short)111);
-        stdStack.pop();
-        stdStack.pop();
-        stdStack.push((short)12);
-        stdStack.push((short)121);
-        stdStack.push((short)1211);
-        stdStack.push((short)12111);
-        stdStack.pop();
-        stdStack.pop();
-        stdStack.pop();
-        stdStack.pop();
-        stdStack.push((short)5);
-        stdStack.pop();
-        stdStack.pop();
-      }
-      end = System.currentTimeMillis();
-      System.out.println("Built-in stack: " + (end-start));
-    }
-  }
-}
diff --git a/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java b/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java
new file mode 100644
index 0000000..d1fc213
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java
@@ -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.
+ */
+
+package org.apache.thrift;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import thrift.test.SafeBytes;
+import thrift.test.UnsafeBytes;
+
+//  test generating types with un-copied byte[]/ByteBuffer input/output
+//
+public class TestUnsafeBinaries extends TestStruct {
+
+  private static byte[] input() {
+    return new byte[]{1, 1};
+  }
+
+  //
+  //  verify that the unsafe_binaries option modifies behavior
+  //
+
+  //  constructor doesn't copy
+  public void testUnsafeConstructor() throws Exception {
+
+    byte[] input = input();
+    UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input));
+
+    input[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{2, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  //  getter doesn't copy
+  //  note: this behavior is the same with/without the flag, but if this default ever changes, the current behavior
+  //        should be retained when using this flag
+  public void testUnsafeGetter(){
+    UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input()));
+
+    byte[] val = struct.getBytes();
+    val[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{2, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  //  setter doesn't copy
+  public void testUnsafeSetter(){
+    UnsafeBytes struct = new UnsafeBytes();
+
+    byte[] val = input();
+    struct.setBytes(val);
+
+    val[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{2, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  //  buffer doens't copy
+  public void testUnsafeBufferFor(){
+    UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input()));
+
+    ByteBuffer val = struct.bufferForBytes();
+    val.array()[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{2, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  //
+  //  verify that the default generator does not change behavior
+  //
+
+  public void testSafeConstructor() {
+
+    byte[] input = input();
+    SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input));
+
+    input[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{1, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  public void testSafeSetter() {
+
+    byte[] input = input();
+    SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input));
+
+    input[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{1, 1},
+        struct.getBytes())
+    );
+
+  }
+
+  public void testSafeBufferFor(){
+    SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input()));
+
+    ByteBuffer val = struct.bufferForBytes();
+    val.array()[0] = 2;
+
+    assertTrue(Arrays.equals(
+        new byte[]{1, 1},
+        struct.getBytes())
+    );
+
+  }
+
+}
diff --git a/lib/java/test/org/apache/thrift/protocol/TestShortStack.java b/lib/java/test/org/apache/thrift/protocol/TestShortStack.java
new file mode 100644
index 0000000..c8e78ee
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/protocol/TestShortStack.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.apache.thrift.protocol;
+
+import junit.framework.TestCase;
+
+public class TestShortStack extends TestCase {
+
+  public void testOps() throws Exception {
+    ShortStack s = new ShortStack(1);
+    s.push((short)10);
+    s.push((short)11);
+    s.push((short)12);
+    assertEquals((short)12, s.pop());
+    assertEquals((short)11, s.pop());
+    s.push((short)40);
+    assertEquals((short)40, s.pop());
+    assertEquals((short)10, s.pop());
+    try {
+      s.pop();
+      fail("should have thrown an exception!");
+    } catch (Exception e) {
+      // yay
+    }
+  }
+}
diff --git a/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java
index 1320749..c2ca1fa 100644
--- a/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java
+++ b/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java
@@ -18,7 +18,7 @@
  */
 package org.apache.thrift.protocol;
 
-import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.thrift.TException;
 import org.apache.thrift.protocol.TJSONProtocol;
@@ -35,13 +35,13 @@
     return false;
   }
 
-  public void testEscapedUnicode() throws TException, IOException {
+  public void testEscapedUnicode() throws TException {
     String jsonString = "\"hello unicode \\u0e01\\ud834\\udd1e world\"";
     String expectedString = "hello unicode \u0e01\ud834\udd1e world";
 
     TMemoryBuffer buffer = new TMemoryBuffer(1000);
     TJSONProtocol protocol = new TJSONProtocol(buffer);
-    buffer.write(jsonString.getBytes("UTF-8"));
+    buffer.write(jsonString.getBytes(StandardCharsets.UTF_8));
 
     assertEquals(expectedString, protocol.readString());
   }
diff --git a/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java b/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java
index 199c707..89cf536 100644
--- a/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java
+++ b/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java
@@ -18,24 +18,10 @@
  */
 package org.apache.thrift.protocol;
 
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.List;
-
 import junit.framework.TestCase;
 
-import org.apache.thrift.Fixtures;
-import org.apache.thrift.TBase;
-import org.apache.thrift.TDeserializer;
-import org.apache.thrift.TException;
 import org.apache.thrift.TSerializer;
-import org.apache.thrift.transport.TMemoryBuffer;
 
-import thrift.test.CompactProtoTestStruct;
-import thrift.test.HolyMoley;
-import thrift.test.Nesting;
-import thrift.test.OneOfEach;
-import thrift.test.Srv;
 import thrift.test.GuessProtocolStruct;
 
 public class TestTProtocolUtil extends TestCase {
diff --git a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
index 0b9c732..9d125b1 100644
--- a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
+++ b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
@@ -18,7 +18,7 @@
  */
 package org.apache.thrift.protocol;
 
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 
 import junit.framework.TestCase;
 
@@ -40,11 +40,7 @@
   }
 
   private String bufToString() {
-    try {
-      return buf.toString("UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new RuntimeException(e);
-    }
+    return buf.toString(StandardCharsets.UTF_8);
   }
 
   public void testHolyMoley() throws TException {
@@ -84,7 +80,7 @@
     struct.unsetDouble_byte_map();
     struct.unsetString_byte_map();
     struct.write(proto);
-    assertEquals("{\"a_byte\":127,\"a_i16\":32000,\"a_i32\":1000000000,\"a_i64\":1099511627775,\"a_double\":5.6789,\"a_string\":\"my string\",\"a_binary\":\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\",\"true_field\":1,\"false_field\":0,\"empty_struct_field\":{},\"byte_list\":[-127,-1,0,1,127],\"i16_list\":[-1,0,1,32767],\"i32_list\":[-1,0,255,65535,16777215,2147483647],\"i64_list\":[-1,0,255,65535,16777215,4294967295,1099511627775,281474976710655,72057594037927935,9223372036854775807],\"double_list\":[0.1,0.2,0.3],\"string_list\":[\"first\",\"second\",\"third\"],\"boolean_list\":[1,1,1,0,0,0],\"struct_list\":[{},{}],\"i32_set\":[1,2,3],\"boolean_set\":[0,1],\"struct_set\":[{}],\"byte_byte_map\":{\"1\":2},\"boolean_byte_map\":{\"0\":0,\"1\":1},\"byte_i16_map\":{\"1\":1,\"2\":-1,\"3\":32767},\"byte_i32_map\":{\"1\":1,\"2\":-1,\"3\":2147483647},\"byte_i64_map\":{\"1\":1,\"2\":-1,\"3\":9223372036854775807},\"byte_double_map\":{\"1\":0.1,\"2\":-0.1,\"3\":1000000.0},\"byte_string_map\":{\"1\":\"\",\"2\":\"blah\",\"3\":\"loooooooooooooong string\"},\"byte_boolean_map\":{\"1\":1,\"2\":0},\"byte_map_map\":{\"0\":{},\"1\":{\"1\":1},\"2\":{\"1\":1,\"2\":2}},\"byte_set_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"byte_list_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]}}", bufToString());
+    assertEquals("{\"a_byte\":127,\"a_i16\":32000,\"a_i32\":1000000000,\"a_i64\":1099511627775,\"a_double\":5.6789,\"a_string\":\"my string\",\"a_binary\":\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\",\"true_field\":1,\"false_field\":0,\"empty_struct_field\":{},\"byte_list\":[-127,-1,0,1,127],\"i16_list\":[-1,0,1,32767],\"i32_list\":[-1,0,255,65535,16777215,2147483647],\"i64_list\":[-1,0,255,65535,16777215,4294967295,1099511627775,281474976710655,72057594037927935,9223372036854775807],\"double_list\":[0.1,0.2,0.3],\"string_list\":[\"first\",\"second\",\"third\"],\"boolean_list\":[1,1,1,0,0,0],\"struct_list\":[{},{}],\"i32_set\":[1,2,3],\"boolean_set\":[0,1],\"struct_set\":[{}],\"byte_byte_map\":{\"1\":2},\"boolean_byte_map\":{\"0\":0,\"1\":1},\"byte_i16_map\":{\"1\":1,\"2\":-1,\"3\":32767},\"byte_i32_map\":{\"1\":1,\"2\":-1,\"3\":2147483647},\"byte_i64_map\":{\"1\":1,\"2\":-1,\"3\":9223372036854775807},\"byte_double_map\":{\"1\":0.1,\"2\":-0.1,\"3\":1000000.1},\"byte_string_map\":{\"1\":\"\",\"2\":\"blah\",\"3\":\"loooooooooooooong string\"},\"byte_boolean_map\":{\"1\":1,\"2\":0},\"byte_map_map\":{\"0\":{},\"1\":{\"1\":1},\"2\":{\"1\":1,\"2\":2}},\"byte_set_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"byte_list_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]}}", bufToString());
   }
 
   public void testThrowsOnCollectionKeys() throws TException {
diff --git a/lib/java/test/org/apache/thrift/server/ServerTestBase.java b/lib/java/test/org/apache/thrift/server/ServerTestBase.java
index e245963..1dee22d 100644
--- a/lib/java/test/org/apache/thrift/server/ServerTestBase.java
+++ b/lib/java/test/org/apache/thrift/server/ServerTestBase.java
@@ -267,7 +267,7 @@
       System.out.println("testOneway(" + Integer.toString(sleepFor) +
                          ") => sleeping...");
       try {
-        Thread.sleep(sleepFor * 1000);
+        Thread.sleep(sleepFor * SLEEP_DELAY);
         System.out.println("Done sleeping!");
       } catch (InterruptedException ie) {
         throw new RuntimeException(ie);
@@ -282,6 +282,7 @@
   public static final String HOST = "localhost";
   public static final int PORT = Integer.valueOf(
     System.getProperty("test.port", "9090"));
+  protected static final int SLEEP_DELAY = 1000;
   protected static final int SOCKET_TIMEOUT = 1500;
   private static final Xtruct XSTRUCT = new Xtruct("Zero", (byte) 1, -3, -5);
   private static final Xtruct2 XSTRUCT2 = new Xtruct2((byte)1, XSTRUCT, 5);
@@ -388,7 +389,7 @@
   public void testIt() throws Exception {
 
     for (TProtocolFactory protoFactory : getProtocols()) {
-      TProcessor processor = useAsyncProcessor() ? new ThriftTest.AsyncProcessor(new AsyncTestHandler()) : new ThriftTest.Processor(new TestHandler());
+      TProcessor processor = useAsyncProcessor() ? new ThriftTest.AsyncProcessor<AsyncTestHandler>(new AsyncTestHandler()) : new ThriftTest.Processor<TestHandler>(new TestHandler());
 
       startServer(processor, protoFactory);
 
@@ -537,7 +538,7 @@
   public void testTransportFactory() throws Exception {
     for (TProtocolFactory protoFactory : getProtocols()) {
       TestHandler handler = new TestHandler();
-      ThriftTest.Processor processor = new ThriftTest.Processor(handler);
+      ThriftTest.Processor<TestHandler> processor = new ThriftTest.Processor<TestHandler>(handler);
 
       final CallCountingTransportFactory factory = new CallCountingTransportFactory(new TFramedTransport.Factory());
 
diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java
index 337dcf8..c353489 100644
--- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java
+++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java
@@ -23,7 +23,7 @@
 public class TestAutoExpandingBuffer extends TestCase {
   public void testExpands() throws Exception {
     // has expected initial capacity
-    AutoExpandingBuffer b = new AutoExpandingBuffer(10, 1.5);
+    AutoExpandingBuffer b = new AutoExpandingBuffer(10);
     assertEquals(10, b.array().length);
 
     // doesn't shrink
diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java
index 2e1f947..83ebc2d 100644
--- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java
+++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java
@@ -32,7 +32,7 @@
   }
 
   public void testIt() throws Exception {
-    AutoExpandingBufferReadTransport t = new AutoExpandingBufferReadTransport(150, 1.5);
+    AutoExpandingBufferReadTransport t = new AutoExpandingBufferReadTransport(150);
 
     TMemoryInputTransport membuf = new TMemoryInputTransport(HUNDRED_BYTES);
 
diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java
index d5f239d..86b5b0d 100644
--- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java
+++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java
@@ -19,26 +19,51 @@
 package org.apache.thrift.transport;
 
 import java.nio.ByteBuffer;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
-import junit.framework.TestCase;
+public class TestAutoExpandingBufferWriteTransport {
 
-public class TestAutoExpandingBufferWriteTransport extends TestCase {
-
+  @Test
   public void testIt() throws Exception {
-    AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1, 1.5);
+    AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1, 0);
+    assertEquals(0, t.getLength());
     assertEquals(1, t.getBuf().array().length);
     byte[] b1 = new byte[]{1,2,3};
     t.write(b1);
-    assertEquals(3, t.getPos());
+    assertEquals(3, t.getLength());
     assertTrue(t.getBuf().array().length >= 3);
     assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(t.getBuf().array(), 0, 3));
 
     t.reset();
+    assertEquals(0, t.getLength());
     assertTrue(t.getBuf().array().length >= 3);
-    assertEquals(0, t.getPos());
     byte[] b2 = new byte[]{4,5};
     t.write(b2);
-    assertEquals(2, t.getPos());
+    assertEquals(2, t.getLength());
     assertEquals(ByteBuffer.wrap(b2), ByteBuffer.wrap(t.getBuf().array(), 0, 2));
+
+    AutoExpandingBufferWriteTransport uut = new AutoExpandingBufferWriteTransport(8, 4);
+    assertEquals(4, uut.getLength());
+    assertEquals(8, uut.getBuf().array().length);
+    uut.write(b1);
+    assertEquals(7, uut.getLength());
+    assertEquals(8, uut.getBuf().array().length);
+    assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(uut.getBuf().array(), 4, 3));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testBadInitialSize() throws IllegalArgumentException {
+    new AutoExpandingBufferWriteTransport(0, 0);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testBadFrontReserveSize() throws IllegalArgumentException {
+    new AutoExpandingBufferWriteTransport(4, -1);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testTooSmallFrontReserveSize() throws IllegalArgumentException {
+    new AutoExpandingBufferWriteTransport(4, 5);
   }
 }
diff --git a/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java b/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java
index 7e889d6..e30d74b 100644
--- a/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java
+++ b/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java
@@ -125,11 +125,11 @@
     assertEquals(0, countingTrans.writeCount);
 
     trans.flush();
-    assertEquals(2, countingTrans.writeCount);
+    assertEquals(1, countingTrans.writeCount);
 
     trans.write(byteSequence(0, 245));
     trans.flush();
-    assertEquals(4, countingTrans.writeCount);
+    assertEquals(2, countingTrans.writeCount);
 
     DataInputStream din = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
     assertEquals(256, din.readInt());
diff --git a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java
index 478407a..032c2eb 100644
--- a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java
+++ b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java
@@ -45,6 +45,10 @@
   throws Exception {
     return TSSLTransportFactory.getClientSocket(HOST, PORT);
   }
+  
+  protected TServerSocket getServerTransport() throws Exception {
+    return TSSLTransportFactory.getServerSocket(PORT);
+  }
 
   @Override
   public void startServer(final TProcessor processor, final TProtocolFactory protoFactory, final TTransportFactory factory)
@@ -52,11 +56,11 @@
     serverThread = new Thread() {
       public void run() {
         try {
-          TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(PORT);
+          TServerTransport serverTransport = getServerTransport();
           final Args args = new Args(serverTransport).processor(processor);
           server = new TSimpleServer(args);
           server.serve();
-        } catch (TTransportException e) {
+        } catch (Exception e) {
           e.printStackTrace();
           assert false;
         }
@@ -64,7 +68,7 @@
     };
 
     serverThread.start();
-    Thread.sleep(1000);
+    Thread.sleep(SLEEP_DELAY);
   }
 
   @Override
diff --git a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java
new file mode 100644
index 0000000..25bf5ce
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package org.apache.thrift.transport;
+
+import java.io.FileInputStream;
+import java.net.InetAddress;
+
+public class TestTSSLTransportFactoryStreamedStore extends TestTSSLTransportFactory {
+  private static String keyStoreLocation = System.getProperty("javax.net.ssl.keyStore");
+  private static String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore");
+  
+  public TestTSSLTransportFactoryStreamedStore() {
+    super();
+    
+    /**
+     *  Override system properties to be able to test passing
+     *  the trustStore and keyStore as input stream
+     */
+    System.setProperty("javax.net.ssl.trustStore", "");
+    System.setProperty("javax.net.ssl.keyStore", "");
+  }
+
+  @Override
+  public TTransport getClientTransport(TTransport underlyingTransport)
+  throws Exception {
+    TSSLTransportFactory.TSSLTransportParameters params = new
+      TSSLTransportFactory.TSSLTransportParameters();
+
+    params.setTrustStore(new FileInputStream(trustStoreLocation),
+                         System.getProperty("javax.net.ssl.trustStorePassword"));
+    
+    return TSSLTransportFactory.getClientSocket(HOST, PORT, 0/*timeout*/, params);
+  }
+
+  @Override
+  protected TServerSocket getServerTransport() throws Exception {
+    TSSLTransportFactory.TSSLTransportParameters params = new
+        TSSLTransportFactory.TSSLTransportParameters();
+    
+    params.setKeyStore(new FileInputStream(keyStoreLocation), 
+                       System.getProperty("javax.net.ssl.keyStorePassword"));
+    
+    return TSSLTransportFactory.getServerSocket(PORT, 0/*timeout*/, InetAddress.getByName(HOST), params);
+  }
+}
\ No newline at end of file
diff --git a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java
index 788395f..36a06e9 100644
--- a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java
+++ b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java
@@ -20,6 +20,7 @@
 package org.apache.thrift.transport;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -332,12 +333,8 @@
         throw new SaslException("Already complete!");
       }
 
-      try {
-        hasProvidedInitialResponse = true;
-        return username.getBytes("UTF-8");
-      } catch (IOException e) {
-        throw new SaslException(e.toString());
-      }
+      hasProvidedInitialResponse = true;
+      return username.getBytes(StandardCharsets.UTF_8);
     }
     public boolean isComplete() { return hasProvidedInitialResponse; }
     public byte[] unwrap(byte[] incoming, int offset, int len) {
@@ -354,11 +351,7 @@
     private String user;
     public String getMechanismName() { return "ANONYMOUS"; }
     public byte[] evaluateResponse(byte[] response) throws SaslException {
-      try {
-        this.user = new String(response, "UTF-8");
-      } catch (IOException e) {
-        throw new SaslException(e.toString());
-      }
+      this.user = new String(response, StandardCharsets.UTF_8);
       return null;
     }
     public boolean isComplete() { return user != null; }
diff --git a/lib/java/test/org/apache/thrift/transport/TestTSimpleFileTransport.java b/lib/java/test/org/apache/thrift/transport/TestTSimpleFileTransport.java
index 5d2fb45..7b880f4 100644
--- a/lib/java/test/org/apache/thrift/transport/TestTSimpleFileTransport.java
+++ b/lib/java/test/org/apache/thrift/transport/TestTSimpleFileTransport.java
@@ -27,21 +27,21 @@
   public void testFresh() throws Exception {
     //Test write side
     Path tempFilePathName = Files.createTempFile("TSimpleFileTransportTest", null);
-    Files.delete(tempFilePathName);        
+    Files.delete(tempFilePathName);
     byte[] input_buf = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     TSimpleFileTransport trans_write = new TSimpleFileTransport(tempFilePathName.toString(),false, true, false);
     assert (!trans_write.isOpen());
     trans_write.open();
     assert(trans_write.isOpen());
     trans_write.write(input_buf);
-    trans_write.write(input_buf,2,2);    
+    trans_write.write(input_buf,2,2);
     trans_write.flush();
     trans_write.close();
-    
+
     //Test read side
     TSimpleFileTransport trans = new TSimpleFileTransport(tempFilePathName.toString(),true, false);
-    assert(trans_write.isOpen());
-    
+    assert(trans.isOpen());
+
     //Simple file trans provides no buffer access
     assert(0 == trans.getBufferPosition());
     assert(null == trans.getBuffer());
@@ -56,19 +56,19 @@
     trans.readAll(buf1, 0, BUFSIZ);
     assert(BUFSIZ == trans.getFilePointer());
     assert(Arrays.equals(new byte[]{1, 2, 3, 4}, buf1));
-    
+
     int bytesRead = trans.read(buf1, 0, BUFSIZ);
     assert(bytesRead > 0);
     for (int i = 0; i < bytesRead; ++i) {
-      assert(buf1[i] == i+5);    
+      assert(buf1[i] == i+5);
     }
-    
+
     trans.seek(0);
     assert(0 == trans.getFilePointer());
     trans.readAll(buf1, 0, BUFSIZ);
     assert(Arrays.equals(new byte[]{1, 2, 3, 4}, buf1));
     assert(BUFSIZ == trans.getFilePointer());
     trans.close();
-    Files.delete(tempFilePathName);      
+    Files.delete(tempFilePathName);
   }
 }
diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js
index bff250f..b32a016 100644
--- a/lib/js/Gruntfile.js
+++ b/lib/js/Gruntfile.js
@@ -3,6 +3,7 @@
 //Prerequisites:
 // Node Setup -   nodejs.org
 // Grunt Setup -  npm install  //reads the ./package.json and installs project dependencies
+// Run grunt -    npx grunt  // uses project-local installed version of grunt (from package.json)
 
 module.exports = function(grunt) {
   'use strict';
@@ -38,112 +39,216 @@
     },
     shell: {
       InstallThriftJS: {
-        command: 'mkdir test/build; mkdir test/build/js; cp src/thrift.js test/build/js/thrift.js'
+        command: 'mkdir -p test/build/js/lib; cp src/thrift.js test/build/js/thrift.js'
       },
       InstallThriftNodeJSDep: {
         command: 'cd ../..; npm install'
       },
+      InstallTestLibs: {
+        command: 'cd test; ant download_jslibs'
+      },
       ThriftGen: {
-        command: '../../compiler/cpp/thrift -gen js -gen js:node -o test ../../test/ThriftTest.thrift'
+        command: [
+          'mkdir -p test/gen-js',
+          '../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/ThriftTest.thrift',
+          '../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/JsDeepConstructorTest.thrift',
+          'mkdir -p test/gen-js-jquery',
+          '../../compiler/cpp/thrift -gen js:jquery --out test/gen-js-jquery ../../test/ThriftTest.thrift',
+          'mkdir -p test/gen-nodejs',
+          '../../compiler/cpp/thrift -gen js:node --out test/gen-nodejs ../../test/ThriftTest.thrift',
+          'mkdir -p test/gen-js-es6',
+          '../../compiler/cpp/thrift -gen js:es6 --out test/gen-js-es6 ../../test/ThriftTest.thrift',
+          'mkdir -p test/gen-nodejs-es6',
+          '../../compiler/cpp/thrift -gen js:node,es6 --out ./test/gen-nodejs-es6 ../../test/ThriftTest.thrift',
+        ].join(' && ')
       },
       ThriftGenJQ: {
         command: '../../compiler/cpp/thrift -gen js:jquery -gen js:node -o test ../../test/ThriftTest.thrift'
       },
       ThriftGenDeepConstructor: {
         command: '../../compiler/cpp/thrift -gen js -o test ../../test/JsDeepConstructorTest.thrift'
-      }
-    },
-    external_daemon: {
+      },
+      ThriftGenDoubleConstants: {
+        command: '../../compiler/cpp/thrift -gen js -o test ../../test/DoubleConstantsTest.thrift'
+      },
       ThriftTestServer: {
         options: {
-          startCheck: function(stdout, stderr) {
-            return (/Thrift Server running on port/).test(stdout);
-          },
-          nodeSpawnOptions: {
-                              cwd: "test",
-                              env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
-                            }
+          async: true,
+          execOptions: {
+            cwd: "./test",
+            env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
+          }
         },
-        cmd: "node",
-        args: ["server_http.js"]
+        command: "node server_http.js",
+      },
+      ThriftTestServerES6: {
+        options: {
+          async: true,
+          execOptions: {
+            cwd: "./test",
+            env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
+          }
+        },
+        command: "node server_http.js --es6",
       },
       ThriftTestServer_TLS: {
         options: {
-          startCheck: function(stdout, stderr) {
-            return (/Thrift Server running on port/).test(stdout);
-          },
-          nodeSpawnOptions: {
-                              cwd: "test",
-                              env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
-                            }
+          async: true,
+          execOptions: {
+            cwd: "./test",
+            env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
+          }
         },
-        cmd: "node",
-        args: ["server_https.js"]
-      }
+        command: "node server_https.js",
+      },
+      ThriftTestServerES6_TLS: {
+        options: {
+          async: true,
+          execOptions: {
+            cwd: "./test",
+            env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"}
+          }
+        },
+        command: "node server_https.js --es6",
+      },
     },
     qunit: {
       ThriftJS: {
         options: {
           urls: [
-            'http://localhost:8088/test-nojq.html'
-          ]
+            'http://localhost:8089/test-nojq.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+          },
         }
       },
       ThriftJSJQ: {
         options: {
           urls: [
-            'http://localhost:8088/test.html'
-          ]
+            'http://localhost:8089/test.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+          },
+        }
+      },
+      ThriftJS_DoubleRendering: {
+        options: {
+          urls: [
+            'http://localhost:8089/test-double-rendering.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+            ignoreHTTPSErrors: true,
+          },
         }
       },
       ThriftWS: {
         options: {
           urls: [
-            'http://localhost:8088/testws.html'
-          ]
+            'http://localhost:8089/testws.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+          },
         }
       },
       ThriftJS_TLS: {
         options: {
-          '--ignore-ssl-errors': true,
           urls: [
-            'https://localhost:8089/test-nojq.html'
-          ]
+            'https://localhost:8091/test-nojq.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+            ignoreHTTPSErrors: true,
+          },
         }
       },
       ThriftJSJQ_TLS: {
         options: {
-          '--ignore-ssl-errors': true,
           urls: [
-            'https://localhost:8089/test.html'
-          ]
+            'https://localhost:8091/test.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+            ignoreHTTPSErrors: true,
+          },
         }
       },
       ThriftWS_TLS: {
         options: {
-          '--ignore-ssl-errors': true,
           urls: [
-            'https://localhost:8089/testws.html'
-          ]
+            'https://localhost:8091/testws.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+            ignoreHTTPSErrors: true,
+          },
         }
       },
       ThriftDeepConstructor: {
         options: {
           urls: [
-            'http://localhost:8088/test-deep-constructor.html'
-          ]
+            'http://localhost:8089/test-deep-constructor.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+          },
+        }
+      },
+      ThriftWSES6: {
+        options: {
+          urls: [
+            'http://localhost:8088/test-es6.html'
+          ],
+          puppeteer: {
+            headless: true,
+            args: ['--no-sandbox'],
+          },
         }
       }
     },
     jshint: {
-      files: ['Gruntfile.js', 'src/**/*.js', 'test/*.js'],
-      options: {
-        // options here to override JSHint defaults
-        globals: {
-          jQuery: true,
-          console: true,
-          module: true,
-          document: true
+      // The main thrift library file. not es6 yet :(
+      lib: {
+        src: ['src/**/*.js'],
+      },
+      // The test files use es6
+      test: {
+        src: ['Gruntfile.js', 'test/*.js'],
+        options: {
+          esversion: 6,
+        }
+      },
+      gen_js_code: {
+        src: ['test/gen-js/*.js', 'test/gen-js-jquery/*.js'],
+      },
+      gen_es6_code: {
+        src: ['test/gen-js-es6/*.js'],
+        options: {
+          esversion: 6,
+        }
+      },
+      gen_node_code: {
+        src: ['test/gen-nodejs/*.js'],
+        options: {
+          node: true,
+        }
+      },
+      gen_node_es6_code: {
+        src: ['test/gen-nodejs-es6/*.js'],
+        options: {
+          node: true,
+          esversion: 6,
         }
       }
     },
@@ -154,19 +259,35 @@
   grunt.loadNpmTasks('grunt-contrib-qunit');
   grunt.loadNpmTasks('grunt-contrib-concat');
   grunt.loadNpmTasks('grunt-jsdoc');
-  grunt.loadNpmTasks('grunt-external-daemon');
-  grunt.loadNpmTasks('grunt-shell');
+  grunt.loadNpmTasks('grunt-shell-spawn');
 
-  grunt.registerTask('test', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen',
-                              'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS',
-                              'shell:ThriftGenDeepConstructor', 'qunit:ThriftDeepConstructor',
-                              'qunit:ThriftJS', 'qunit:ThriftJS_TLS',
-                              'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS'
-                             ]);
-  grunt.registerTask('default', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen',
-                                 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS',
-                                 'qunit:ThriftJS', 'qunit:ThriftJS_TLS',
-                                 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS',
-                                 'concat', 'uglify', 'jsdoc'
-                                ]);
+  grunt.registerTask('wait', 'Wait just one second for server to start', function () {
+    var done = this.async();
+    setTimeout(function() {
+      done(true);
+    }, 1000);
+  });
+
+  grunt.registerTask('installAndGenerate', [
+    'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen',
+    'shell:ThriftGenDeepConstructor', 'shell:ThriftGenDoubleConstants',
+    'shell:InstallTestLibs',
+  ]);
+
+  grunt.registerTask('test', [
+    'installAndGenerate',
+    'jshint',
+    'shell:ThriftTestServer', 'shell:ThriftTestServer_TLS',
+    'shell:ThriftTestServerES6', 'shell:ThriftTestServerES6_TLS',
+    'wait',
+    'qunit:ThriftDeepConstructor',
+    'qunit:ThriftJS', 'qunit:ThriftJS_TLS',
+    'qunit:ThriftJS_DoubleRendering',
+    'qunit:ThriftWS',
+    'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS',
+    'qunit:ThriftWSES6',
+    'shell:ThriftTestServer:kill', 'shell:ThriftTestServer_TLS:kill',
+    'shell:ThriftTestServerES6:kill', 'shell:ThriftTestServerES6_TLS:kill',
+  ]);
+  grunt.registerTask('default', ['test', 'concat', 'uglify', 'jsdoc']);
 };
diff --git a/lib/js/README.md b/lib/js/README.md
index dfa6e82..9d51e2a 100644
--- a/lib/js/README.md
+++ b/lib/js/README.md
@@ -38,19 +38,12 @@
 sources from the internet. To build the JavaScript branch
 of Apache Thrift execute the command:
 
-    grunt
+    npx grunt
     
-This runs the grunt build tool, linting all of the source
-files, setting up and running the tests, concatenating and
-minifying the main libraries and generating the html 
-documentation.
-
-If grunt is not installed you can install it with npm
-like this:
-
-   sudo npm install -g grunt-cli
-   npm install grunt --save-dev
-
+This runs the grunt build tool (from within `./node_modules/.bin/`),
+linting all of the source files, setting up and running the
+tests, concatenating and minifying the main libraries and
+generating the html documentation.
 
 Tree
 ----
diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json
new file mode 100644
index 0000000..63d81c3
--- /dev/null
+++ b/lib/js/package-lock.json
@@ -0,0 +1,3777 @@
+{
+  "name": "thrift",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+    },
+    "agent-base": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+      "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+      "dev": true,
+      "requires": {
+        "es6-promisify": "^5.0.0"
+      }
+    },
+    "ajv": {
+      "version": "5.5.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "co": "^4.6.0",
+        "fast-deep-equal": "^1.0.0",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.3.0"
+      }
+    },
+    "align-text": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2",
+        "longest": "^1.0.1",
+        "repeat-string": "^1.5.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      },
+      "dependencies": {
+        "sprintf-js": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+          "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+          "dev": true
+        }
+      }
+    },
+    "arr-diff": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+      "dev": true
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+      "dev": true
+    },
+    "array-each": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
+      "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=",
+      "dev": true
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+      "dev": true
+    },
+    "array-slice": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
+      "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
+      "dev": true
+    },
+    "array-unique": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+      "dev": true
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "dev": true
+    },
+    "assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+      "dev": true
+    },
+    "async": {
+      "version": "1.5.2",
+      "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
+    },
+    "async-limiter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+      "dev": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true,
+      "optional": true
+    },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "dev": true
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true,
+      "optional": true
+    },
+    "aws4": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+      "dev": true,
+      "optional": true
+    },
+    "babylon": {
+      "version": "7.0.0-beta.19",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
+      "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A=="
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "dev": true,
+      "requires": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "bluebird": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
+      "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg=="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+      "dev": true,
+      "requires": {
+        "arr-flatten": "^1.1.0",
+        "array-unique": "^0.3.2",
+        "extend-shallow": "^2.0.1",
+        "fill-range": "^4.0.0",
+        "isobject": "^3.0.1",
+        "repeat-element": "^1.1.2",
+        "snapdragon": "^0.8.1",
+        "snapdragon-node": "^2.0.1",
+        "split-string": "^3.0.2",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+      "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+      "dev": true,
+      "requires": {
+        "pako": "~0.2.0"
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "buffer-shims": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+      "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=",
+      "dev": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "dev": true,
+      "requires": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      }
+    },
+    "camelcase": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+      "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+      "dev": true
+    },
+    "camelcase-keys": {
+      "version": "2.1.0",
+      "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^2.0.0",
+        "map-obj": "^1.0.0"
+      }
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true,
+      "optional": true
+    },
+    "catharsis": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
+      "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
+      "requires": {
+        "underscore-contrib": "~0.3.0"
+      }
+    },
+    "center-align": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+      "dev": true,
+      "requires": {
+        "align-text": "^0.1.3",
+        "lazy-cache": "^1.0.3"
+      }
+    },
+    "chalk": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+      "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "cli": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
+      "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=",
+      "dev": true,
+      "requires": {
+        "exit": "0.1.2",
+        "glob": "^7.1.1"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.1.3",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        }
+      }
+    },
+    "cliui": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+      "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+      "dev": true,
+      "requires": {
+        "center-align": "^0.1.1",
+        "right-align": "^0.1.1",
+        "wordwrap": "0.0.2"
+      }
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "dev": true,
+      "optional": true
+    },
+    "coffeescript": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz",
+      "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=",
+      "dev": true
+    },
+    "collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "dev": true,
+      "requires": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      }
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "colors": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+      "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+      "dev": true
+    },
+    "combined-stream": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "component-emitter": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "console-browserify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+      "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+      "dev": true,
+      "requires": {
+        "date-now": "^0.1.4"
+      }
+    },
+    "copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "currently-unhandled": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+      "dev": true,
+      "requires": {
+        "array-find-index": "^1.0.1"
+      }
+    },
+    "cycle": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
+      "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=",
+      "dev": true,
+      "optional": true
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "date-now": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+      "dev": true
+    },
+    "dateformat": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+      "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1",
+        "meow": "^3.3.0"
+      }
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "dev": true
+    },
+    "decode-uri-component": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "dev": true
+    },
+    "define-property": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+      "dev": true,
+      "requires": {
+        "is-descriptor": "^1.0.2",
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
+    "detect-file": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+      "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+      "dev": true
+    },
+    "dom-serializer": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+      "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+      "dev": true,
+      "requires": {
+        "domelementtype": "~1.1.1",
+        "entities": "~1.1.1"
+      },
+      "dependencies": {
+        "domelementtype": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+          "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
+          "dev": true
+        },
+        "entities": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+          "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+          "dev": true
+        }
+      }
+    },
+    "domelementtype": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+      "dev": true
+    },
+    "domhandler": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
+      "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
+      "dev": true,
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+      "dev": true,
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "entities": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
+      "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=",
+      "dev": true
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es6-promise": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+      "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==",
+      "dev": true
+    },
+    "es6-promisify": {
+      "version": "5.0.0",
+      "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+      "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+      "dev": true,
+      "requires": {
+        "es6-promise": "^4.0.3"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+    },
+    "esprima": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+      "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+      "dev": true
+    },
+    "eventemitter2": {
+      "version": "0.4.14",
+      "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+      "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+      "dev": true
+    },
+    "exit": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+      "dev": true
+    },
+    "expand-brackets": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.3.3",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "posix-character-classes": "^0.1.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "expand-tilde": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+      "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+      "dev": true,
+      "requires": {
+        "homedir-polyfill": "^1.0.1"
+      }
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "dev": true
+    },
+    "extend-shallow": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+      "dev": true,
+      "requires": {
+        "assign-symbols": "^1.0.0",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "extglob": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+      "dev": true,
+      "requires": {
+        "array-unique": "^0.3.2",
+        "define-property": "^1.0.0",
+        "expand-brackets": "^2.1.4",
+        "extend-shallow": "^2.0.1",
+        "fragment-cache": "^0.2.1",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "extract-zip": {
+      "version": "1.6.7",
+      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
+      "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
+      "dev": true,
+      "requires": {
+        "concat-stream": "1.6.2",
+        "debug": "2.6.9",
+        "mkdirp": "0.5.1",
+        "yauzl": "2.4.1"
+      }
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true
+    },
+    "eyes": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+      "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
+      "dev": true,
+      "optional": true
+    },
+    "fast-deep-equal": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+      "dev": true,
+      "optional": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true,
+      "optional": true
+    },
+    "fd-slicer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+      "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+      "dev": true,
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
+    "figures": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+      "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "fill-range": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+      "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-number": "^3.0.0",
+        "repeat-string": "^1.6.1",
+        "to-regex-range": "^2.1.0"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "find-up": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+      "dev": true,
+      "requires": {
+        "path-exists": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "findup-sync": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+      "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+      "dev": true,
+      "requires": {
+        "glob": "~5.0.0"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "5.0.15",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+          "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+          "dev": true,
+          "requires": {
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "2 || 3",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        }
+      }
+    },
+    "fined": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
+      "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.2",
+        "is-plain-object": "^2.0.3",
+        "object.defaults": "^1.1.0",
+        "object.pick": "^1.2.0",
+        "parse-filepath": "^1.0.1"
+      }
+    },
+    "flagged-respawn": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
+      "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=",
+      "dev": true
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
+    "for-own": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+      "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.1"
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true,
+      "optional": true
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fragment-cache": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+      "dev": true,
+      "requires": {
+        "map-cache": "^0.2.2"
+      }
+    },
+    "fs-extra": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
+      "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "jsonfile": "^2.1.0",
+        "klaw": "^1.0.0"
+      },
+      "dependencies": {
+        "klaw": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+          "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "graceful-fs": "^4.1.9"
+          }
+        }
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "get-stdin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+      "dev": true
+    },
+    "get-value": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+      "dev": true
+    },
+    "getobject": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+      "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+      "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.2",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "global-modules": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+      "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+      "dev": true,
+      "requires": {
+        "global-prefix": "^1.0.1",
+        "is-windows": "^1.0.1",
+        "resolve-dir": "^1.0.0"
+      }
+    },
+    "global-prefix": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+      "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.2",
+        "homedir-polyfill": "^1.0.1",
+        "ini": "^1.3.4",
+        "is-windows": "^1.0.1",
+        "which": "^1.2.14"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+    },
+    "grunt": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz",
+      "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==",
+      "dev": true,
+      "requires": {
+        "coffeescript": "~1.10.0",
+        "dateformat": "~1.0.12",
+        "eventemitter2": "~0.4.13",
+        "exit": "~0.1.1",
+        "findup-sync": "~0.3.0",
+        "glob": "~7.0.0",
+        "grunt-cli": "~1.2.0",
+        "grunt-known-options": "~1.1.0",
+        "grunt-legacy-log": "~2.0.0",
+        "grunt-legacy-util": "~1.1.1",
+        "iconv-lite": "~0.4.13",
+        "js-yaml": "~3.5.2",
+        "minimatch": "~3.0.2",
+        "mkdirp": "~0.5.1",
+        "nopt": "~3.0.6",
+        "path-is-absolute": "~1.0.0",
+        "rimraf": "~2.6.2"
+      },
+      "dependencies": {
+        "grunt-cli": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+          "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
+          "dev": true,
+          "requires": {
+            "findup-sync": "~0.3.0",
+            "grunt-known-options": "~1.1.0",
+            "nopt": "~3.0.6",
+            "resolve": "~1.1.0"
+          }
+        },
+        "nopt": {
+          "version": "3.0.6",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+          "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+          "dev": true,
+          "requires": {
+            "abbrev": "1"
+          }
+        }
+      }
+    },
+    "grunt-cli": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.1.tgz",
+      "integrity": "sha512-UwBRu/QpAjDc53DRLEkyilFdL0zenpxu+fddTIlsF/KJqdNcHaQmvyu1W3cDesZ9rqqZdKK5A8+QDIyLUEWoZQ==",
+      "dev": true,
+      "requires": {
+        "grunt-known-options": "~1.1.0",
+        "interpret": "~1.1.0",
+        "liftoff": "~2.5.0",
+        "nopt": "~4.0.1",
+        "v8flags": "~3.0.2"
+      }
+    },
+    "grunt-contrib-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz",
+      "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "source-map": "^0.5.3"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-contrib-jshint": {
+      "version": "1.1.0",
+      "resolved": "http://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-1.1.0.tgz",
+      "integrity": "sha1-Np2QmyWTxA6L55lAshNAhQx5Oaw=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.1",
+        "hooker": "^0.2.3",
+        "jshint": "~2.9.4"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-contrib-qunit": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.0.1.tgz",
+      "integrity": "sha512-s994+ipKwc+oUUIWaGIw1soyID4pExSGMd/cHQN5h0p8KbIjR1Le3ZC3giSDDKXtZFE0i+Obf0uIjNvjftX2Cw==",
+      "dev": true,
+      "requires": {
+        "eventemitter2": "^5.0.1",
+        "p-each-series": "^1.0.0",
+        "puppeteer": "1.7.0"
+      },
+      "dependencies": {
+        "eventemitter2": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
+          "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-contrib-uglify": {
+      "version": "1.0.2",
+      "resolved": "http://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz",
+      "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "lodash": "^4.0.1",
+        "maxmin": "^1.1.0",
+        "uglify-js": "~2.6.2",
+        "uri-path": "^1.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "grunt-jsdoc": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.3.0.tgz",
+      "integrity": "sha512-gC66TCRXeQMj3HIyqVSBJm8zdUz43e5vaG/PLO/627A1edbJnzxhJV7nF0KqLwMM0RDNu1istC6fvfnYqFKi3w==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^6.0.5",
+        "jsdoc": "~3.5.5",
+        "marked": "^0.5.0"
+      },
+      "dependencies": {
+        "marked": {
+          "version": "0.5.1",
+          "resolved": "https://registry.npmjs.org/marked/-/marked-0.5.1.tgz",
+          "integrity": "sha512-iUkBZegCZou4AdwbKTwSW/lNDcz5OuRSl3qdcl31Ia0B2QPG0Jn+tKblh/9/eP9/6+4h27vpoh8wel/vQOV0vw==",
+          "dev": true
+        }
+      }
+    },
+    "grunt-known-options": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz",
+      "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==",
+      "dev": true
+    },
+    "grunt-legacy-log": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz",
+      "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==",
+      "dev": true,
+      "requires": {
+        "colors": "~1.1.2",
+        "grunt-legacy-log-utils": "~2.0.0",
+        "hooker": "~0.2.3",
+        "lodash": "~4.17.5"
+      }
+    },
+    "grunt-legacy-log-utils": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz",
+      "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==",
+      "dev": true,
+      "requires": {
+        "chalk": "~2.4.1",
+        "lodash": "~4.17.10"
+      }
+    },
+    "grunt-legacy-util": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz",
+      "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==",
+      "dev": true,
+      "requires": {
+        "async": "~1.5.2",
+        "exit": "~0.1.1",
+        "getobject": "~0.1.0",
+        "hooker": "~0.2.3",
+        "lodash": "~4.17.10",
+        "underscore.string": "~3.3.4",
+        "which": "~1.3.0"
+      }
+    },
+    "grunt-shell-spawn": {
+      "version": "0.3.10",
+      "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.10.tgz",
+      "integrity": "sha1-gbuNRX7EfTGCqH1jCO+EXd+5SI8=",
+      "dev": true,
+      "requires": {
+        "grunt": ">=0.4.x",
+        "sync-exec": "~0.6.2"
+      }
+    },
+    "gzip-size": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz",
+      "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=",
+      "dev": true,
+      "requires": {
+        "browserify-zlib": "^0.1.4",
+        "concat-stream": "^1.4.1"
+      }
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "dev": true,
+      "optional": true
+    },
+    "har-validator": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
+      "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "ajv": "^5.3.0",
+        "har-schema": "^2.0.0"
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "has-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+      "dev": true,
+      "requires": {
+        "get-value": "^2.0.6",
+        "has-values": "^1.0.0",
+        "isobject": "^3.0.0"
+      }
+    },
+    "has-values": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "hasha": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz",
+      "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "is-stream": "^1.0.1",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "homedir-polyfill": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
+      "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
+      "dev": true,
+      "requires": {
+        "parse-passwd": "^1.0.0"
+      }
+    },
+    "hooker": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+      "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+      "dev": true
+    },
+    "hosted-git-info": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+      "dev": true
+    },
+    "htmlparser2": {
+      "version": "3.8.3",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
+      "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
+      "dev": true,
+      "requires": {
+        "domelementtype": "1",
+        "domhandler": "2.3",
+        "domutils": "1.5",
+        "entities": "1.0",
+        "readable-stream": "1.1"
+      }
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "https-proxy-agent": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+      "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^4.1.0",
+        "debug": "^3.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        }
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "interpret": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
+      "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=",
+      "dev": true
+    },
+    "is-absolute": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+      "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+      "dev": true,
+      "requires": {
+        "is-relative": "^1.0.0",
+        "is-windows": "^1.0.1"
+      }
+    },
+    "is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-buffer": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+      "dev": true
+    },
+    "is-builtin-module": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+      "dev": true,
+      "requires": {
+        "builtin-modules": "^1.0.0"
+      }
+    },
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "dev": true,
+      "requires": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-glob": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+      "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.0"
+      }
+    },
+    "is-number": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+      "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
+    "is-relative": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+      "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+      "dev": true,
+      "requires": {
+        "is-unc-path": "^1.0.0"
+      }
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "dev": true,
+      "optional": true
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true,
+      "optional": true
+    },
+    "is-unc-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+      "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+      "dev": true,
+      "requires": {
+        "unc-path-regex": "^0.1.2"
+      }
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+      "dev": true
+    },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+      "dev": true
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.5.5",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
+      "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.2",
+        "esprima": "^2.6.0"
+      }
+    },
+    "js2xmlparser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
+      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
+      "requires": {
+        "xmlcreate": "^1.0.1"
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true
+    },
+    "jsdoc": {
+      "version": "3.5.5",
+      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
+      "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
+      "requires": {
+        "babylon": "7.0.0-beta.19",
+        "bluebird": "~3.5.0",
+        "catharsis": "~0.8.9",
+        "escape-string-regexp": "~1.0.5",
+        "js2xmlparser": "~3.0.0",
+        "klaw": "~2.0.0",
+        "marked": "~0.3.6",
+        "mkdirp": "~0.5.1",
+        "requizzle": "~0.2.1",
+        "strip-json-comments": "~2.0.1",
+        "taffydb": "2.6.2",
+        "underscore": "~1.8.3"
+      }
+    },
+    "jshint": {
+      "version": "2.9.6",
+      "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.6.tgz",
+      "integrity": "sha512-KO9SIAKTlJQOM4lE64GQUtGBRpTOuvbrRrSZw3AhUxMNG266nX9hK2cKA4SBhXOj0irJGyNyGSLT62HGOVDEOA==",
+      "dev": true,
+      "requires": {
+        "cli": "~1.0.0",
+        "console-browserify": "1.1.x",
+        "exit": "0.1.x",
+        "htmlparser2": "3.8.x",
+        "lodash": "~4.17.10",
+        "minimatch": "~3.0.2",
+        "phantom": "~4.0.1",
+        "phantomjs-prebuilt": "~2.1.7",
+        "shelljs": "0.3.x",
+        "strip-json-comments": "1.0.x",
+        "unicode-5.2.0": "^0.7.5"
+      },
+      "dependencies": {
+        "strip-json-comments": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
+          "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=",
+          "dev": true
+        }
+      }
+    },
+    "jslint": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.0.tgz",
+      "integrity": "sha512-RoCsyICcKA+6TFsbys9DpKTfPVaC71Mm5QSjvrWA0lDVN+LIvx6apa42FFisMqmCTvJ8DxkcoQGJ0j7m3kTVow==",
+      "dev": true,
+      "requires": {
+        "exit": "~0.1.2",
+        "glob": "~7.1.2",
+        "nopt": "~3.0.1",
+        "readable-stream": "~2.1.5"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.1.3",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "nopt": {
+          "version": "3.0.6",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+          "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+          "dev": true,
+          "requires": {
+            "abbrev": "1"
+          }
+        },
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.1.5",
+          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz",
+          "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=",
+          "dev": true,
+          "requires": {
+            "buffer-shims": "^1.0.0",
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~1.0.6",
+            "string_decoder": "~0.10.x",
+            "util-deprecate": "~1.0.1"
+          }
+        }
+      }
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true,
+      "optional": true
+    },
+    "json-schema-traverse": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+      "dev": true,
+      "optional": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true,
+      "optional": true
+    },
+    "jsonfile": {
+      "version": "2.4.0",
+      "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+      "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "kew": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz",
+      "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=",
+      "dev": true,
+      "optional": true
+    },
+    "kind-of": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+      "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+      "dev": true
+    },
+    "klaw": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
+      "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
+      "requires": {
+        "graceful-fs": "^4.1.9"
+      }
+    },
+    "lazy-cache": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+      "dev": true
+    },
+    "liftoff": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
+      "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=",
+      "dev": true,
+      "requires": {
+        "extend": "^3.0.0",
+        "findup-sync": "^2.0.0",
+        "fined": "^1.0.1",
+        "flagged-respawn": "^1.0.0",
+        "is-plain-object": "^2.0.4",
+        "object.map": "^1.0.0",
+        "rechoir": "^0.6.2",
+        "resolve": "^1.1.7"
+      },
+      "dependencies": {
+        "findup-sync": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
+          "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
+          "dev": true,
+          "requires": {
+            "detect-file": "^1.0.0",
+            "is-glob": "^3.1.0",
+            "micromatch": "^3.0.4",
+            "resolve-dir": "^1.0.1"
+          }
+        }
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^2.2.0",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "strip-bom": "^2.0.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.11",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "dev": true
+    },
+    "longest": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+      "dev": true
+    },
+    "loud-rejection": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+      "dev": true,
+      "requires": {
+        "currently-unhandled": "^0.4.1",
+        "signal-exit": "^3.0.0"
+      }
+    },
+    "make-iterator": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
+      "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^6.0.2"
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+      "dev": true
+    },
+    "map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+      "dev": true
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "dev": true,
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "marked": {
+      "version": "0.3.19",
+      "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
+      "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg=="
+    },
+    "maxmin": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz",
+      "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.0.0",
+        "figures": "^1.0.1",
+        "gzip-size": "^1.0.0",
+        "pretty-bytes": "^1.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "meow": {
+      "version": "3.7.0",
+      "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+      "dev": true,
+      "requires": {
+        "camelcase-keys": "^2.0.0",
+        "decamelize": "^1.1.2",
+        "loud-rejection": "^1.0.0",
+        "map-obj": "^1.0.1",
+        "minimist": "^1.1.3",
+        "normalize-package-data": "^2.3.4",
+        "object-assign": "^4.0.1",
+        "read-pkg-up": "^1.0.1",
+        "redent": "^1.0.0",
+        "trim-newlines": "^1.0.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "micromatch": {
+      "version": "3.1.10",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+      "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "braces": "^2.3.1",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "extglob": "^2.0.4",
+        "fragment-cache": "^0.2.1",
+        "kind-of": "^6.0.2",
+        "nanomatch": "^1.2.9",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.2"
+      }
+    },
+    "mime": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
+      "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
+      "dev": true
+    },
+    "mime-db": {
+      "version": "1.37.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
+      "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.21",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
+      "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
+      "dev": true,
+      "requires": {
+        "mime-db": "~1.37.0"
+      }
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+    },
+    "mixin-deep": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.2",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "nanomatch": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "fragment-cache": "^0.2.1",
+        "is-windows": "^1.0.2",
+        "kind-of": "^6.0.2",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      }
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "nopt": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+      "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+      "requires": {
+        "abbrev": "1",
+        "osenv": "^0.1.4"
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+      "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "is-builtin-module": "^1.0.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "dev": true,
+      "optional": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-copy": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+      "dev": true,
+      "requires": {
+        "copy-descriptor": "^0.1.0",
+        "define-property": "^0.2.5",
+        "kind-of": "^3.0.3"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "object-visit": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.0"
+      }
+    },
+    "object.defaults": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
+      "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=",
+      "dev": true,
+      "requires": {
+        "array-each": "^1.0.1",
+        "array-slice": "^1.0.0",
+        "for-own": "^1.0.0",
+        "isobject": "^3.0.0"
+      }
+    },
+    "object.map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
+      "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=",
+      "dev": true,
+      "requires": {
+        "for-own": "^1.0.0",
+        "make-iterator": "^1.0.0"
+      }
+    },
+    "object.pick": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
+    "p-each-series": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz",
+      "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=",
+      "dev": true,
+      "requires": {
+        "p-reduce": "^1.0.0"
+      }
+    },
+    "p-reduce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz",
+      "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=",
+      "dev": true
+    },
+    "pako": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+      "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+      "dev": true
+    },
+    "parse-filepath": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
+      "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=",
+      "dev": true,
+      "requires": {
+        "is-absolute": "^1.0.0",
+        "map-cache": "^0.2.0",
+        "path-root": "^0.1.1"
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.2.0"
+      }
+    },
+    "parse-passwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+      "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+      "dev": true
+    },
+    "pascalcase": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+      "dev": true
+    },
+    "path-exists": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+      "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+      "dev": true,
+      "requires": {
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
+    "path-root": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
+      "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=",
+      "dev": true,
+      "requires": {
+        "path-root-regex": "^0.1.0"
+      }
+    },
+    "path-root-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
+      "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
+      "dev": true
+    },
+    "path-type": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+      "dev": true
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "dev": true,
+      "optional": true
+    },
+    "phantom": {
+      "version": "4.0.12",
+      "resolved": "https://registry.npmjs.org/phantom/-/phantom-4.0.12.tgz",
+      "integrity": "sha512-Tz82XhtPmwCk1FFPmecy7yRGZG2btpzY2KI9fcoPT7zT9det0CcMyfBFPp1S8DqzsnQnm8ZYEfdy528mwVtksA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "phantomjs-prebuilt": "^2.1.16",
+        "split": "^1.0.1",
+        "winston": "^2.4.0"
+      }
+    },
+    "phantomjs-prebuilt": {
+      "version": "2.1.16",
+      "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz",
+      "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "es6-promise": "^4.0.3",
+        "extract-zip": "^1.6.5",
+        "fs-extra": "^1.0.0",
+        "hasha": "^2.2.0",
+        "kew": "^0.7.0",
+        "progress": "^1.1.8",
+        "request": "^2.81.0",
+        "request-progress": "^2.0.1",
+        "which": "^1.2.10"
+      }
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "posix-character-classes": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+      "dev": true
+    },
+    "pretty-bytes": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
+      "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1",
+        "meow": "^3.1.0"
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+      "dev": true
+    },
+    "progress": {
+      "version": "1.1.8",
+      "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+      "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
+      "dev": true,
+      "optional": true
+    },
+    "proxy-from-env": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+      "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=",
+      "dev": true
+    },
+    "psl": {
+      "version": "1.1.29",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
+      "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
+      "dev": true,
+      "optional": true
+    },
+    "punycode": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+      "dev": true,
+      "optional": true
+    },
+    "puppeteer": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.7.0.tgz",
+      "integrity": "sha512-f+1DxKHPqce6CXUBz2eVO2WcATeVeQSOPG9GYaGObEZDCiCEUwG+gogjMsrvn7he2wHTqNVb5p6RUrwmr8XFBA==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.1.0",
+        "extract-zip": "^1.6.6",
+        "https-proxy-agent": "^2.2.1",
+        "mime": "^2.0.3",
+        "progress": "^2.0.0",
+        "proxy-from-env": "^1.0.0",
+        "rimraf": "^2.6.1",
+        "ws": "^5.1.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        },
+        "progress": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz",
+          "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==",
+          "dev": true
+        }
+      }
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "dev": true,
+      "optional": true
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "dev": true,
+      "requires": {
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "1.1.14",
+      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+      "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.1",
+        "isarray": "0.0.1",
+        "string_decoder": "~0.10.x"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+          "dev": true
+        }
+      }
+    },
+    "rechoir": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+      "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+      "dev": true,
+      "requires": {
+        "resolve": "^1.1.6"
+      }
+    },
+    "redent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+      "dev": true,
+      "requires": {
+        "indent-string": "^2.1.0",
+        "strip-indent": "^1.0.1"
+      }
+    },
+    "regex-not": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
+    "repeat-element": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "^1.0.0"
+      }
+    },
+    "request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "request-progress": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz",
+      "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "throttleit": "^1.0.0"
+      }
+    },
+    "requizzle": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
+      "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
+      "requires": {
+        "underscore": "~1.6.0"
+      },
+      "dependencies": {
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
+        }
+      }
+    },
+    "resolve": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+      "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+      "dev": true
+    },
+    "resolve-dir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+      "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.0",
+        "global-modules": "^1.0.0"
+      }
+    },
+    "resolve-url": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+      "dev": true
+    },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true
+    },
+    "right-align": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+      "dev": true,
+      "requires": {
+        "align-text": "^0.1.1"
+      }
+    },
+    "rimraf": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.5"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "safe-regex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+      "dev": true,
+      "requires": {
+        "ret": "~0.1.10"
+      }
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+      "dev": true
+    },
+    "set-value": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-extendable": "^0.1.1",
+        "is-plain-object": "^2.0.3",
+        "split-string": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "shelljs": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
+      "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "snapdragon": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+      "dev": true,
+      "requires": {
+        "base": "^0.11.1",
+        "debug": "^2.2.0",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "map-cache": "^0.2.2",
+        "source-map": "^0.5.6",
+        "source-map-resolve": "^0.5.0",
+        "use": "^3.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "snapdragon-node": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.0",
+        "snapdragon-util": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "snapdragon-util": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.2.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+      "dev": true
+    },
+    "source-map-resolve": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+      "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+      "dev": true,
+      "requires": {
+        "atob": "^2.1.1",
+        "decode-uri-component": "^0.2.0",
+        "resolve-url": "^0.2.1",
+        "source-map-url": "^0.4.0",
+        "urix": "^0.1.0"
+      }
+    },
+    "source-map-url": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+      "dev": true
+    },
+    "spdx-correct": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
+      "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
+      "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==",
+      "dev": true
+    },
+    "split": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
+      "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "through": "2"
+      }
+    },
+    "split-string": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.0"
+      }
+    },
+    "sprintf-js": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz",
+      "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=",
+      "dev": true
+    },
+    "sshpk": {
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
+      "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      }
+    },
+    "stack-trace": {
+      "version": "0.0.10",
+      "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+      "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
+      "dev": true,
+      "optional": true
+    },
+    "static-extend": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+      "dev": true,
+      "requires": {
+        "define-property": "^0.2.5",
+        "object-copy": "^0.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+      "dev": true
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "dev": true,
+      "requires": {
+        "is-utf8": "^0.2.0"
+      }
+    },
+    "strip-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1"
+      }
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "sync-exec": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz",
+      "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=",
+      "dev": true
+    },
+    "taffydb": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
+      "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg="
+    },
+    "throttleit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+      "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=",
+      "dev": true,
+      "optional": true
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+      "dev": true,
+      "optional": true
+    },
+    "to-object-path": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "to-regex": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "regex-not": "^1.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
+    "to-regex-range": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+      "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "repeat-string": "^1.6.1"
+      }
+    },
+    "tough-cookie": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      }
+    },
+    "trim-newlines": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true
+    },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "2.6.4",
+      "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz",
+      "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=",
+      "dev": true,
+      "requires": {
+        "async": "~0.2.6",
+        "source-map": "~0.5.1",
+        "uglify-to-browserify": "~1.0.0",
+        "yargs": "~3.10.0"
+      },
+      "dependencies": {
+        "async": {
+          "version": "0.2.10",
+          "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz",
+          "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
+          "dev": true
+        }
+      }
+    },
+    "uglify-to-browserify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+      "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+      "dev": true
+    },
+    "unc-path-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+      "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
+      "dev": true
+    },
+    "underscore": {
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
+    },
+    "underscore-contrib": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
+      "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
+      "requires": {
+        "underscore": "1.6.0"
+      },
+      "dependencies": {
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
+        }
+      }
+    },
+    "underscore.string": {
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz",
+      "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "^1.0.3",
+        "util-deprecate": "^1.0.2"
+      }
+    },
+    "unicode-5.2.0": {
+      "version": "0.7.5",
+      "resolved": "https://registry.npmjs.org/unicode-5.2.0/-/unicode-5.2.0-0.7.5.tgz",
+      "integrity": "sha512-KVGLW1Bri30x00yv4HNM8kBxoqFXr0Sbo55735nvrlsx4PYBZol3UtoWgO492fSwmsetzPEZzy73rbU8OGXJcA==",
+      "dev": true
+    },
+    "union-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "get-value": "^2.0.6",
+        "is-extendable": "^0.1.1",
+        "set-value": "^0.4.3"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "set-value": {
+          "version": "0.4.3",
+          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-extendable": "^0.1.1",
+            "is-plain-object": "^2.0.1",
+            "to-object-path": "^0.3.0"
+          }
+        }
+      }
+    },
+    "unset-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+      "dev": true,
+      "requires": {
+        "has-value": "^0.3.1",
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "has-value": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+          "dev": true,
+          "requires": {
+            "get-value": "^2.0.3",
+            "has-values": "^0.1.4",
+            "isobject": "^2.0.0"
+          },
+          "dependencies": {
+            "isobject": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+              "dev": true,
+              "requires": {
+                "isarray": "1.0.0"
+              }
+            }
+          }
+        },
+        "has-values": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+          "dev": true
+        }
+      }
+    },
+    "uri-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz",
+      "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=",
+      "dev": true
+    },
+    "urix": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+      "dev": true
+    },
+    "use": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+      "dev": true
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "uuid": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+      "dev": true,
+      "optional": true
+    },
+    "v8flags": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.2.tgz",
+      "integrity": "sha512-6sgSKoFw1UpUPd3cFdF7QGnrH6tDeBgW1F3v9gy8gLY0mlbiBXq8soy8aQpY6xeeCjH5K+JvC62Acp7gtl7wWA==",
+      "dev": true,
+      "requires": {
+        "homedir-polyfill": "^1.0.1"
+      }
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "window-size": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+      "dev": true
+    },
+    "winston": {
+      "version": "2.4.4",
+      "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz",
+      "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "async": "~1.0.0",
+        "colors": "1.0.x",
+        "cycle": "1.0.x",
+        "eyes": "0.1.x",
+        "isstream": "0.1.x",
+        "stack-trace": "0.0.x"
+      },
+      "dependencies": {
+        "async": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz",
+          "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=",
+          "dev": true,
+          "optional": true
+        },
+        "colors": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+          "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "wordwrap": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+      "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+      "dev": true
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "ws": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
+      "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+      "dev": true,
+      "requires": {
+        "async-limiter": "~1.0.0"
+      }
+    },
+    "xmlcreate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
+      "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8="
+    },
+    "yargs": {
+      "version": "3.10.0",
+      "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+      "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^1.0.2",
+        "cliui": "^2.1.0",
+        "decamelize": "^1.0.0",
+        "window-size": "0.1.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+          "dev": true
+        }
+      }
+    },
+    "yauzl": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+      "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+      "dev": true,
+      "requires": {
+        "fd-slicer": "~1.0.1"
+      }
+    }
+  }
+}
diff --git a/lib/js/package.json b/lib/js/package.json
index 421de93..a59cdc4 100644
--- a/lib/js/package.json
+++ b/lib/js/package.json
@@ -1,16 +1,16 @@
 {
   "name": "thrift",
-  "version": "0.11.0",
+  "version": "1.0.0",
   "devDependencies": {
-    "grunt": "^0.4.5",
+    "grunt": "^1.0.2",
     "grunt-cli": "^1.2.0",
     "grunt-contrib-concat": "^1.0.1",
     "grunt-contrib-jshint": "^1.0.0",
-    "grunt-contrib-qunit": "^1.2.0",
+    "grunt-contrib-qunit": "^3.0.1",
     "grunt-contrib-uglify": "^1.0.1",
-    "grunt-external-daemon": "^1.1.0",
-    "grunt-jsdoc": "^2.2.0",
-    "grunt-shell": "^1.3.0"
+    "grunt-jsdoc": "^2.2.1",
+    "grunt-shell-spawn": "^0.3.10",
+    "jslint": "^0.12.0"
   },
   "dependencies": {
     "jsdoc": "^3.5.5",
diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js
index d308c46..9bf8127 100644
--- a/lib/js/src/thrift.js
+++ b/lib/js/src/thrift.js
@@ -46,7 +46,7 @@
      * @const {string} Version
      * @memberof Thrift
      */
-    Version: '0.11.0',
+    Version: '1.0.0',
 
     /**
      * Thrift IDL type string to Id mapping.
@@ -572,18 +572,11 @@
           var clientCallback = callback;
           return function(msg) {
             self.setRecvBuffer(msg);
-            clientCallback();
+            if (clientCallback) {
+                clientCallback();
+            }
           };
         }()));
-        if(callback) {
-          this.callbacks.push((function() {
-            var clientCallback = callback;
-            return function(msg) {
-              self.setRecvBuffer(msg);
-              clientCallback();
-            };
-          }()));
-        }
       } else {
         //Queue the send to go out __onOpen
         this.send_pending.push({
@@ -599,8 +592,8 @@
           //If the user made calls before the connection was fully
           //open, send them now
           this.send_pending.forEach(function(elem) {
-             this.socket.send(elem.buf);
-             this.callbacks.push((function() {
+             self.socket.send(elem.buf);
+             self.callbacks.push((function() {
                var clientCallback = elem.cb;
                return function(msg) {
                   self.setRecvBuffer(msg);
@@ -1265,7 +1258,12 @@
 
     /** Deserializes the end of a list. */
     readListEnd: function() {
-        this.readFieldEnd();
+        var pos = this.rpos.pop() - 2;
+        var st = this.rstack;
+        st.pop();
+        if (st instanceof Array && st.length > pos && st[pos].length > 0) {
+          st.push(st[pos].shift());
+        }
     },
 
     /**
@@ -1321,7 +1319,11 @@
             if (f.length === 0) {
                 r.value = undefined;
             } else {
-                r.value = f.shift();
+                if (!f.isReversed) {
+                    f.reverse();
+                    f.isReversed = true;
+                }
+                r.value = f.pop();
             }
         } else if (f instanceof Object) {
            for (var i in f) {
@@ -1440,6 +1442,9 @@
                 }
                 this.readListEnd();
                 return null;
+
+            default:
+                throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA);
         }
     }
 };
diff --git a/lib/js/test/build.properties b/lib/js/test/build.properties
new file mode 100644
index 0000000..8463668
--- /dev/null
+++ b/lib/js/test/build.properties
@@ -0,0 +1,5 @@
+# Maven Ant tasks Jar details
+mvn.ant.task.version=2.1.3
+mvn.repo=http://repo1.maven.org/maven2
+mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version}
+mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar
diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml
index a905fde..04c1360 100755
--- a/lib/js/test/build.xml
+++ b/lib/js/test/build.xml
@@ -31,17 +31,21 @@
   <!-- the root directory, where you unpack thrift distibution (e.g. thrift-0.x.x.tar.gz) -->
   <property name="thrift.dir" location="../../../" />
   <property name="thrift.java.dir" location="${thrift.dir}/lib/java" />
+  <property name="build.tools.dir" location="${thrift.java.dir}/build/tools/"/>
+  <property file="${basedir}/build.properties"/>
 
   <!-- Include the base java properties file -->
-  <property file="${thrift.java.dir}/build.properties" />
+  <property file="${thrift.java.dir}/gradle.properties" />
 
   <property name="thrift.compiler" location="${thrift.dir}/compiler/cpp/thrift" />
 
   <path id="libs.classpath">
-    <fileset dir="${thrift.java.dir}/build/">
-      <include name="*.jar" />
+    <fileset dir="${thrift.java.dir}/build/libs">
+      <include name="libthrift*.jar" />
+      <exclude name="libthrift*javadoc.jar" />
+      <exclude name="libthrift*sources.jar" />
     </fileset>
-    <fileset dir="${thrift.java.dir}/build/lib">
+    <fileset dir="${thrift.java.dir}/build/deps">
       <include name="*.jar" />
     </fileset>
     <fileset dir="${build}/lib">
@@ -59,15 +63,16 @@
       <condition>
         <not>
           <resourcecount count="2">
-            <fileset id="fs" dir="${thrift.java.dir}/build">
+            <fileset id="fs" dir="${thrift.java.dir}/build/libs">
               <include name="libthrift*.jar" />
               <exclude name="libthrift*javadoc.jar" />
+              <exclude name="libthrift*sources.jar" />
             </fileset>
           </resourcecount>
         </not>
       </condition>
       You need libthrift*.jar and libthrift*test.jar located at
-      ${thrift.java.dir}/build
+      ${thrift.java.dir}/build/libs
       Did you compile Thrift Java library and its test suite by "ant compile-test"?
     </fail>
     <fail>
@@ -84,6 +89,7 @@
 
   <target name="init" depends="dependencies">
     <tstamp />
+    <mkdir dir="${build.tools.dir}"/>
     <mkdir dir="${build}"/>
     <mkdir dir="${build}/js/lib"/>
     <mkdir dir="${build}/lib"/>
@@ -92,10 +98,13 @@
     <mkdir dir="${build}/test/log"/>
   </target>
 
-  <target name="jslibs" depends="init, proxy">
+  <target name="download_jslibs">
     <get src="http://code.jquery.com/jquery-1.11.3.min.js" dest="${build}/js/lib/jquery.js" usetimestamp="true"/>
-    <get src="http://code.jquery.com/qunit/qunit-1.18.0.js" dest="${build}/js/lib/qunit.js" usetimestamp="true"/>
-    <get src="http://code.jquery.com/qunit/qunit-1.18.0.css" dest="${build}/js/lib/qunit.css" usetimestamp="true"/>
+    <get src="http://code.jquery.com/qunit/qunit-2.6.2.js" dest="${build}/js/lib/qunit.js" usetimestamp="true"/>
+    <get src="http://code.jquery.com/qunit/qunit-2.6.2.css" dest="${build}/js/lib/qunit.css" usetimestamp="true"/>
+  </target>
+
+  <target name="jslibs" depends="init, proxy, download_jslibs">
   </target>
 
   <target name="compile" description="compile the test suite" depends="init, generate, resolve">
@@ -161,6 +170,9 @@
     <exec executable="${thrift.compiler}" failonerror="true">
       <arg line="--gen js:jquery ${thrift.dir}/test/ThriftTest.thrift" />
     </exec>
+    <exec executable="${thrift.compiler}" failonerror="true">
+      <arg line="--gen js:jquery ${thrift.dir}/test/DoubleConstantsTest.thrift" />
+    </exec>
   </target>
 
   <target name="test" description="run test suite (lint, unittest)" depends="lint, unittest"/>
@@ -207,7 +219,17 @@
     <delete dir="${genjs}" />
   </target>
 
-  <target name="resolve" unless="mvn.finished">
+  <target name="mvn.ant.tasks.download" depends="init,mvn.ant.tasks.check" unless="mvn.ant.tasks.found">
+    <get src="${mvn.ant.task.url}/${mvn.ant.task.jar}" dest="${build.tools.dir}/${mvn.ant.task.jar}" usetimestamp="true"/>
+  </target>
+
+  <target name="mvn.ant.tasks.check">
+    <condition property="mvn.ant.tasks.found">
+      <typefound uri="antlib:org.apache.maven.artifact.ant" name="artifact"/>
+    </condition>
+  </target>
+
+  <target name="resolve" depends="mvn.ant.tasks.download" unless="mvn.finished">
     <typedef uri="antlib:org.apache.maven.artifact.ant" classpath="${thrift.java.dir}/build/tools/${mvn.ant.task.jar}"/>
 
     <artifact:dependencies filesetId="js.test.dependency.jars">
diff --git a/lib/js/test/deep-constructor.test.js b/lib/js/test/deep-constructor.test.js
index 336fc15..82d3a1e 100644
--- a/lib/js/test/deep-constructor.test.js
+++ b/lib/js/test/deep-constructor.test.js
@@ -1,6 +1,6 @@
 function serialize(data) {
-  var transport = new Thrift.Transport('/service');
-  var protocol = new Thrift.Protocol(transport);
+  const transport = new Thrift.Transport('/service');
+  const protocol = new Thrift.Protocol(transport);
   protocol.writeMessageBegin('', 0, 0);
   data.write(protocol);
   protocol.writeMessageEnd();
@@ -8,11 +8,11 @@
 }
 
 function deserialize(serialized, type) {
-  var transport = new Thrift.Transport('/service');
+  const transport = new Thrift.Transport('/service');
   transport.setRecvBuffer(serialized);
-  var protocol = new Thrift.Protocol(transport);
+  const protocol = new Thrift.Protocol(transport);
   protocol.readMessageBegin();
-  var data = new type();
+  const data = new type();
   data.read(protocol);
   protocol.readMessageEnd();
   return data;
@@ -61,7 +61,13 @@
           DB: new Simple({value: 'k'})
         }
       ]
-    }
+    },
+
+    list_of_list_field: [
+       ['one', 'two'],
+       ['three', 'four'],
+       ['five', 'six']
+    ]
   }
   );
 }
@@ -108,7 +114,13 @@
           DB: {value: 'k'}
         }
       ]
-    }
+    },
+
+    list_of_list_field: [
+      ['one', 'two'],
+      ['three', 'four'],
+      ['five', 'six']
+   ]
   };
 }
 
@@ -125,38 +137,44 @@
     assert.equal(obj.struct_nested_containers_field[0][0].C[1].value, 'i');
     assert.equal(obj.struct_nested_containers_field2.D[0].DA.value, 'j');
     assert.equal(obj.struct_nested_containers_field2.D[1].DB.value, 'k');
+    assert.equal(obj.list_of_list_field[0][0], 'one');
+    assert.equal(obj.list_of_list_field[0][1], 'two');
+    assert.equal(obj.list_of_list_field[1][0], 'three');
+    assert.equal(obj.list_of_list_field[1][1], 'four');
+    assert.equal(obj.list_of_list_field[2][0], 'five');
+    assert.equal(obj.list_of_list_field[2][1], 'six');
 }
 
-var cases = {
+const cases = {
 
   'Serialize/deserialize simple struct should return equal object': function(assert) {
-    var tObj = new Simple({value: 'a'});
-    var received = deserialize(serialize(tObj), Simple);
+    const tObj = new Simple({value: 'a'});
+    const received = deserialize(serialize(tObj), Simple);
     assert.ok(tObj !== received);
     assert.deepEqual(received, tObj);
   },
 
 
   'Serialize/deserialize should return equal object': function(assert) {
-    var tObj = createThriftObj();
-    var received = deserialize(serialize(tObj), Complex);
+    const tObj = createThriftObj();
+    const received = deserialize(serialize(tObj), Complex);
     assert.ok(tObj !== received);
     assert.deepEqual(received, tObj);
   },
 
   'Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects': function(assert) {
-    var tObj1 = createThriftObj();
-    var tObj2 = new Complex(createJsObj());
+    const tObj1 = createThriftObj();
+    const tObj2 = new Complex(createJsObj());
     assertValues(tObj2, assert);
     assert.equal(serialize(tObj2), serialize(tObj1));
   },
 
   'Modifications to args object should not affect constructed Thrift object': function(assert) {
 
-    var args = createJsObj();
+    const args = createJsObj();
     assertValues(args, assert);
 
-    var tObj = new Complex(args);
+    const tObj = new Complex(args);
     assertValues(tObj, assert);
 
     args.struct_field.value = 'ZZZ';
@@ -175,7 +193,7 @@
   },
 
   'nulls are ok': function(assert) {
-    var tObj = new Complex({
+    const tObj = new Complex({
       struct_field: null,
       struct_list_field: null,
       struct_set_field: null,
@@ -183,7 +201,7 @@
       struct_nested_containers_field: null,
       struct_nested_containers_field2: null
     });
-    var received = deserialize(serialize(tObj), Complex);
+    const received = deserialize(serialize(tObj), Complex);
     assert.ok(tObj !== received);
     assert.deepEqual(tObj, received);
   }
@@ -191,5 +209,5 @@
 };
 
 Object.keys(cases).forEach(function(caseName) {
-  test(caseName, cases[caseName]);
+  QUnit.test(caseName, cases[caseName]);
 });
diff --git a/lib/js/test/jsTestDriver.conf b/lib/js/test/jsTestDriver.conf
index b9702cd..eb1588c 100755
--- a/lib/js/test/jsTestDriver.conf
+++ b/lib/js/test/jsTestDriver.conf
@@ -7,6 +7,7 @@
 # dependencies
   - build/js/lib/jquery.js
   - build/js/thrift.js
+  - gen-js/DoubleConstantsTest_constants.js
   - gen-js/ThriftTest_types.js
   - gen-js/ThriftTest.js
 # the test suite
diff --git a/lib/js/test/server_http.js b/lib/js/test/server_http.js
index 1115474..8380c3a 100644
--- a/lib/js/test/server_http.js
+++ b/lib/js/test/server_http.js
@@ -17,33 +17,39 @@
  * under the License.
  */
 
-//This HTTP server is designed to serve the test.html browser
+//  This HTTP server is designed to serve the test.html browser
 //  based JavaScript test page (which must be in the current directory).
 //  This server also supplies the Thrift based test service, which depends
 //  on the standard ThriftTest.thrift IDL service (which must be compiled
 //  for Node and browser based JavaScript in ./gen-nodejs and ./gen-js
 //  respectively).
+//
+//  Using the command flag --es6, this server can be run using nodejs code built
+//  for the es6 environment or for pre-es6 environment.
+//
 
-var thrift = require('../../nodejs/lib/thrift');
-var ThriftTestSvc = require('./gen-nodejs/ThriftTest.js');
-var ThriftTestHandler = require('./test_handler').ThriftTestHandler;
+const thrift = require('../../nodejs/lib/thrift');
+const es6Mode = process.argv.includes('--es6');
+const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs';
+const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`);
+const ThriftTestHandler = require('./test_handler').ThriftTestHandler;
 
-var ThriftTestSvcOpt = {
+const ThriftTestSvcOpt = {
 	transport: thrift.TBufferedTransport,
 	protocol: thrift.TJSONProtocol,
 	processor: ThriftTestSvc,
 	handler: ThriftTestHandler
 };
 
-var ThriftWebServerOptions = {
-	files: '.',
+const ThriftWebServerOptions = {
+	files: __dirname,
 	services: {
 		'/service': ThriftTestSvcOpt
 	}
 };
 
-var server = thrift.createWebServer(ThriftWebServerOptions);
-var port = 8088;
+const server = thrift.createWebServer(ThriftWebServerOptions);
+const port = es6Mode ? 8088 : 8089;
 server.listen(port);
-console.log('Serving files from: ' + __dirname);
-console.log('Http/Thrift Server running on port: ' + port);
+console.log(`Serving files from: ${__dirname}`);
+console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`);
diff --git a/lib/js/test/server_https.js b/lib/js/test/server_https.js
index 7e78d9e..1a171dd 100644
--- a/lib/js/test/server_https.js
+++ b/lib/js/test/server_https.js
@@ -26,21 +26,23 @@
 //  support libraries for test.html (jquery.js, qunit.js and qunit.css
 //  in ./build/js/lib).
 
-var fs = require('fs');
-var thrift = require('../../nodejs/lib/thrift');
-var ThriftTestSvc = require('./gen-nodejs/ThriftTest.js');
-var ThriftTestHandler = require('./test_handler').ThriftTestHandler;
+const fs = require('fs');
+const thrift = require('../../nodejs/lib/thrift');
+const es6Mode = process.argv.includes('--es6');
+const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs';
+const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`);
+const ThriftTestHandler = require('./test_handler').ThriftTestHandler;
 
 //Setup the I/O stack options for the ThriftTest service
-var ThriftTestSvcOpt = {
+const ThriftTestSvcOpt = {
   transport: thrift.TBufferedTransport,
   protocol: thrift.TJSONProtocol,
   processor: ThriftTestSvc,
   handler: ThriftTestHandler
 };
 
-var ThriftWebServerOptions = {
-  files: '.',
+const ThriftWebServerOptions = {
+  files: __dirname,
   tls: {
      key: fs.readFileSync('../../../test/keys/server.key'),
      cert: fs.readFileSync('../../../test/keys/server.crt')
@@ -50,8 +52,8 @@
   }
 };
 
-var server = thrift.createWebServer(ThriftWebServerOptions);
-var port = 8089;
+const server = thrift.createWebServer(ThriftWebServerOptions);
+const port = es6Mode ? 8090 : 8091;
 server.listen(port);
-console.log('Serving files from: ' + __dirname);
-console.log('Http/Thrift Server running on port: ' + port);
+console.log(`Serving files from: ${__dirname}`);
+console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`);
diff --git a/lib/js/test/test-async.js b/lib/js/test/test-async.js
index b56f2a2..8c6b13e 100644
--- a/lib/js/test/test-async.js
+++ b/lib/js/test/test-async.js
@@ -30,128 +30,130 @@
 
 
 // all Languages in UTF-8
-var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
+const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
 
-function checkRecursively(map1, map2) {
+function checkRecursively(assert, map1, map2) {
   if (typeof map1 !== 'function' && typeof map2 !== 'function') {
     if (!map1 || typeof map1 !== 'object') {
-        equal(map1, map2);
+        assert.equal(map1, map2);
     } else {
-      for (var key in map1) {
-        checkRecursively(map1[key], map2[key]);
+      for (let key in map1) {
+        checkRecursively(assert, map1[key], map2[key]);
       }
     }
   }
 }
 
-module('Base Types');
+QUnit.module('Base Types');
 
-  asyncTest('Void', function() {
-    expect(1);
+  QUnit.test('Void', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
     client.testVoid(function(result) {
-      equal(result, undefined);
-      QUnit.start();
+      assert.equal(result, undefined);
+      done();
     });
   });
 
 
-  asyncTest('String', function() {
-    expect(3);
-    QUnit.stop(2);
+  QUnit.test('String', function(assert) {
+    assert.expect(3);
+    const done = assert.async(3);
     client.testString('', function(result) {
-       equal(result, '');
-       QUnit.start();
+       assert.equal(result, '');
+       done();
     });
     client.testString(stringTest, function(result) {
-       equal(result, stringTest);
-       QUnit.start();
+       assert.equal(result, stringTest);
+       done();
     });
 
-    var specialCharacters = 'quote: \" backslash:' +
+    const specialCharacters = 'quote: \" backslash:' +
           ' forwardslash-escaped: \/ ' +
           ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
           ' now-all-of-them-together: "\\\/\b\n\r\t' +
           ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><';
     client.testString(specialCharacters, function(result) {
-       equal(result, specialCharacters);
-       QUnit.start();
+       assert.equal(result, specialCharacters);
+       done();
     });
   });
-  asyncTest('Double', function() {
-    expect(4);
-    QUnit.stop(3);
+  QUnit.test('Double', function(assert) {
+    assert.expect(4);
+    const done = assert.async(4);
     client.testDouble(0, function(result) {
-       equal(result, 0);
-       QUnit.start();
+       assert.equal(result, 0);
+       done();
     });
     client.testDouble(-1, function(result) {
-       equal(result, -1);
-       QUnit.start();
+       assert.equal(result, -1);
+       done();
     });
     client.testDouble(3.14, function(result) {
-       equal(result, 3.14);
-       QUnit.start();
+       assert.equal(result, 3.14);
+       done();
     });
     client.testDouble(Math.pow(2, 60), function(result) {
-       equal(result, Math.pow(2, 60));
-       QUnit.start();
+       assert.equal(result, Math.pow(2, 60));
+       done();
     });
   });
   // TODO: add testBinary()
-  asyncTest('Byte', function() {
-    expect(2);
-    QUnit.stop();
+  QUnit.test('Byte', function(assert) {
+    assert.expect(2);
+    const done = assert.async(2);
     client.testByte(0, function(result) {
-       equal(result, 0);
-       QUnit.start();
+       assert.equal(result, 0);
+       done();
     });
     client.testByte(0x01, function(result) {
-       equal(result, 0x01);
-       QUnit.start();
+       assert.equal(result, 0x01);
+       done();
     });
   });
-  asyncTest('I32', function() {
-    expect(3);
-    QUnit.stop(2);
+  QUnit.test('I32', function(assert) {
+    assert.expect(3);
+    const done = assert.async(3);
     client.testI32(0, function(result) {
-       equal(result, 0);
-       QUnit.start();
+       assert.equal(result, 0);
+       done();
     });
     client.testI32(Math.pow(2, 30), function(result) {
-       equal(result, Math.pow(2, 30));
-       QUnit.start();
+       assert.equal(result, Math.pow(2, 30));
+       done();
     });
     client.testI32(-Math.pow(2, 30), function(result) {
-       equal(result, -Math.pow(2, 30));
-       QUnit.start();
+       assert.equal(result, -Math.pow(2, 30));
+       done();
     });
   });
-  asyncTest('I64', function() {
-    expect(3);
-    QUnit.stop(2);
+  QUnit.test('I64', function(assert) {
+    assert.expect(3);
+    const done = assert.async(3);
     client.testI64(0, function(result) {
-       equal(result, 0);
-       QUnit.start();
+       assert.equal(result, 0);
+       done();
     });
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     client.testI64(Math.pow(2, 52), function(result) {
-       equal(result, Math.pow(2, 52));
-       QUnit.start();
+       assert.equal(result, Math.pow(2, 52));
+       done();
     });
     client.testI64(-Math.pow(2, 52), function(result) {
-       equal(result, -Math.pow(2, 52));
-       QUnit.start();
+       assert.equal(result, -Math.pow(2, 52));
+       done();
     });
   });
 
 
 
 
-module('Structured Types');
+QUnit.module('Structured Types');
 
-  asyncTest('Struct', function() {
-    expect(5);
-    var structTestInput = new ThriftTest.Xtruct();
+  QUnit.test('Struct', function(assert) {
+    assert.expect(5);
+    const done = assert.async();
+    const structTestInput = new ThriftTest.Xtruct();
     structTestInput.string_thing = 'worked';
     structTestInput.byte_thing = 0x01;
     structTestInput.i32_thing = Math.pow(2, 30);
@@ -159,148 +161,159 @@
     structTestInput.i64_thing = Math.pow(2, 52);
 
     client.testStruct(structTestInput, function(result) {
-      equal(result.string_thing, structTestInput.string_thing);
-      equal(result.byte_thing, structTestInput.byte_thing);
-      equal(result.i32_thing, structTestInput.i32_thing);
-      equal(result.i64_thing, structTestInput.i64_thing);
-      equal(JSON.stringify(result), JSON.stringify(structTestInput));
-      QUnit.start();
+      assert.equal(result.string_thing, structTestInput.string_thing);
+      assert.equal(result.byte_thing, structTestInput.byte_thing);
+      assert.equal(result.i32_thing, structTestInput.i32_thing);
+      assert.equal(result.i64_thing, structTestInput.i64_thing);
+      assert.equal(JSON.stringify(result), JSON.stringify(structTestInput));
+      done();
     });
   });
 
-  asyncTest('Nest', function() {
-    expect(7);
-    var xtrTestInput = new ThriftTest.Xtruct();
+  QUnit.test('Nest', function(assert) {
+    assert.expect(7);
+    const done = assert.async();
+    const xtrTestInput = new ThriftTest.Xtruct();
     xtrTestInput.string_thing = 'worked';
     xtrTestInput.byte_thing = 0x01;
     xtrTestInput.i32_thing = Math.pow(2, 30);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     xtrTestInput.i64_thing = Math.pow(2, 52);
 
-    var nestTestInput = new ThriftTest.Xtruct2();
+    const nestTestInput = new ThriftTest.Xtruct2();
     nestTestInput.byte_thing = 0x02;
     nestTestInput.struct_thing = xtrTestInput;
     nestTestInput.i32_thing = Math.pow(2, 15);
 
     client.testNest(nestTestInput, function(result) {
-      equal(result.byte_thing, nestTestInput.byte_thing);
-      equal(result.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
-      equal(result.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
-      equal(result.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
-      equal(result.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing);
-      equal(result.i32_thing, nestTestInput.i32_thing);
-      equal(JSON.stringify(result), JSON.stringify(nestTestInput));
-      QUnit.start();
+      assert.equal(result.byte_thing, nestTestInput.byte_thing);
+      assert.equal(result.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
+      assert.equal(result.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
+      assert.equal(result.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
+      assert.equal(result.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing);
+      assert.equal(result.i32_thing, nestTestInput.i32_thing);
+      assert.equal(JSON.stringify(result), JSON.stringify(nestTestInput));
+      done();
     });
   });
 
-  asyncTest('Map', function() {
-    expect(3);
-    var mapTestInput = {7: 77, 8: 88, 9: 99};
+  QUnit.test('Map', function(assert) {
+    assert.expect(3);
+    const done = assert.async();
+    const mapTestInput = {7: 77, 8: 88, 9: 99};
 
     client.testMap(mapTestInput, function(result) {
-      for (var key in result) {
-        equal(result[key], mapTestInput[key]);
+      for (let key in result) {
+        assert.equal(result[key], mapTestInput[key]);
       }
-      QUnit.start();
+      done();
     });
   });
 
-  asyncTest('StringMap', function() {
-    expect(6);
-    var mapTestInput = {
+  QUnit.test('StringMap', function(assert) {
+    assert.expect(6);
+    const done = assert.async();
+    const mapTestInput = {
       'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key',
       'longValue': stringTest, stringTest: 'long key'
     };
 
     client.testStringMap(mapTestInput, function(result) {
-      for (var key in result) {
-        equal(result[key], mapTestInput[key]);
+      for (let key in result) {
+        assert.equal(result[key], mapTestInput[key]);
       }
-      QUnit.start();
+      done();
     });
   });
 
-  asyncTest('Set', function() {
-    expect(1);
-    var setTestInput = [1, 2, 3];
+  QUnit.test('Set', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
+    const setTestInput = [1, 2, 3];
     client.testSet(setTestInput, function(result) {
-      ok(result, setTestInput);
-      QUnit.start();
+      assert.ok(result, setTestInput);
+      done();
     });
   });
 
-  asyncTest('List', function() {
-    expect(1);
-    var listTestInput = [1, 2, 3];
+  QUnit.test('List', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
+    const listTestInput = [1, 2, 3];
     client.testList(listTestInput, function(result) {
-      ok(result, listTestInput);
-      QUnit.start();
+      assert.ok(result, listTestInput);
+      done();
     });
   });
 
-  asyncTest('Enum', function() {
-    expect(1);
+  QUnit.test('Enum', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
     client.testEnum(ThriftTest.Numberz.ONE, function(result) {
-      equal(result, ThriftTest.Numberz.ONE);
-      QUnit.start();
+      assert.equal(result, ThriftTest.Numberz.ONE);
+      done();
     });
   });
 
-  asyncTest('TypeDef', function() {
-    expect(1);
+  QUnit.test('TypeDef', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
     client.testTypedef(69, function(result) {
-      equal(result, 69);
-      QUnit.start();
+      assert.equal(result, 69);
+      done();
     });
   });
 
 
-module('deeper!');
+QUnit.module('deeper!');
 
-  asyncTest('MapMap', function() {
-    expect(16);
-    var mapMapTestExpectedResult = {
+  QUnit.test('MapMap', function(assert) {
+    assert.expect(16);
+    const done = assert.async();
+    const mapMapTestExpectedResult = {
       '4': {'1': 1, '2': 2, '3': 3, '4': 4},
       '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1}
     };
 
     client.testMapMap(1, function(result) {
-      for (var key in result) {
-        for (var key2 in result[key]) {
-          equal(result[key][key2], mapMapTestExpectedResult[key][key2]);
+      for (let key in result) {
+        for (let key2 in result[key]) {
+          assert.equal(result[key][key2], mapMapTestExpectedResult[key][key2]);
         }
       }
-      checkRecursively(result, mapMapTestExpectedResult);
-      QUnit.start();
+      checkRecursively(assert, result, mapMapTestExpectedResult);
+      done();
     });
   });
 
 
-module('Exception');
+QUnit.module('Exception');
 
-  asyncTest('Xception', function() {
-    expect(2);
+  QUnit.test('Xception', function(assert) {
+    assert.expect(2);
+    const done = assert.async();
     client.testException('Xception', function(e) {
-      equal(e.errorCode, 1001);
-      equal(e.message, 'Xception');
-      QUnit.start();
+      assert.equal(e.errorCode, 1001);
+      assert.equal(e.message, 'Xception');
+      done();
     });
   });
 
-  asyncTest('no Exception', 0, function() {
-    expect(1);
+  QUnit.test('no Exception', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
     client.testException('no Exception', function(e) {
-      ok(!e);
-      QUnit.start();
+      assert.ok(!e);
+      done();
     });
   });
 
-module('Insanity');
+QUnit.module('Insanity');
 
-  asyncTest('testInsanity', function() {
-    expect(24);
-    var insanity = {
+  QUnit.test('testInsanity', function(assert) {
+    assert.expect(24);
+    const done = assert.async();
+    const insanity = {
       '1': {
         '2': {
           'userMap': { '5': 5, '8': 8 },
@@ -338,11 +351,20 @@
       '2': { '6': { 'userMap': null, 'xtructs': null } }
     };
     client.testInsanity(new ThriftTest.Insanity(), function(res) {
-      ok(res, JSON.stringify(res));
-      ok(insanity, JSON.stringify(insanity));
-      checkRecursively(res, insanity);
-      QUnit.start();
+      assert.ok(res, JSON.stringify(res));
+      assert.ok(insanity, JSON.stringify(insanity));
+      checkRecursively(assert, res, insanity);
+      done();
     });
   });
 
+QUnit.module('Oneway');
 
+  QUnit.test('testOneway', function(assert) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testOneway(1, function(result) {
+      assert.equal(result, undefined);
+      done();
+    });
+  });
diff --git a/lib/js/test/test-deep-constructor.html b/lib/js/test/test-deep-constructor.html
index 5835dc8..dfc0da6 100755
--- a/lib/js/test/test-deep-constructor.html
+++ b/lib/js/test/test-deep-constructor.html
@@ -25,17 +25,17 @@
   <script src="build/js/thrift.js"         type="text/javascript" charset="utf-8"></script>
   <script src="gen-js/JsDeepConstructorTest_types.js" type="text/javascript" charset="utf-8"></script>
   <!-- jQuery -->
-  <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.js" charset="utf-8"></script>
+  <script type="text/javascript" src="build/js/lib/jquery.js" charset="utf-8"></script>
 
   <!-- QUnit Test framework-->
-  <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.14.0.js" charset="utf-8"></script>
-  <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css" type="text/css" media="screen" />
+	<script type="text/javascript" src="build/js/lib/qunit.js" charset="utf-8"></script>
+	<link rel="stylesheet" href="build/js/lib/qunit.css" type="text/css" media="screen" />
 
   <!-- the Test Suite-->
   <script type="text/javascript" src="deep-constructor.test.js" charset="utf-8"></script>
 </head>
 <body>
-  <h1 id="qunit-header">Thrift Javascript Bindings: Deep Constructor Test (<a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=test/JsDeepConstructorTest.thrift;hb=HEAD">JsDeepConstructorTest.thrift</a>)</h1>
+  <h1 id="qunit-header">Thrift Javascript Bindings: Deep Constructor Test (<a href="https://github.com/apache/thrift/blob/master/test/JsDeepConstructorTest.thrift">JsDeepConstructorTest.thrift</a>)</h1>
   <h2 id="qunit-banner"></h2>
   <div id="qunit-testrunner-toolbar"></div>
   <h2 id="qunit-userAgent"></h2>
diff --git a/lib/js/test/test-double-rendering.html b/lib/js/test/test-double-rendering.html
new file mode 100644
index 0000000..7a430a5
--- /dev/null
+++ b/lib/js/test/test-double-rendering.html
@@ -0,0 +1,55 @@
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+      <title>Rendering Double Constants in JS: Unit Test</title>
+
+      <script src="build/js/thrift.js"         type="text/javascript" charset="utf-8"></script>
+      <script src="gen-js/ThriftTest_types.js" type="text/javascript" charset="utf-8"></script>
+      <script src="gen-js/ThriftTest.js"       type="text/javascript" charset="utf-8"></script>
+      <!-- double constants to check -->
+      <script src="gen-js/DoubleConstantsTest_types.js"         type="text/javascript" charset="utf-8"></script>
+
+      <!-- jQuery -->
+      <script type="text/javascript" src="build/js/lib/jquery.js" charset="utf-8"></script>
+
+      <!-- QUnit Test framework-->
+      <script type="text/javascript" src="build/js/lib/qunit.js" charset="utf-8"></script>
+      <link rel="stylesheet" href="build/js/lib/qunit.css" type="text/css" media="screen" />
+
+      <!-- the Test Suite-->
+      <script type="text/javascript" src="test-double-rendering.js" charset="utf-8"></script>
+    </head>
+<body>
+  <h1 id="qunit-header">Rendering Double Constants in JS: Unit Test</h1>
+  <h2 id="qunit-banner"></h2>
+  <div id="qunit-testrunner-toolbar"></div>
+  <h2 id="qunit-userAgent"></h2>
+  <ol id="qunit-tests"><li><!-- get valid xhtml strict--></li></ol>
+  <!-- Uncomment this to check the validity. This significantly slows down the test.
+  <p>
+      <a href="http://validator.w3.org/check/referer"><img
+          src="http://www.w3.org/Icons/valid-xhtml10"
+          alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+  </p>
+  -->
+</body>
+</html>
diff --git a/lib/js/test/test-double-rendering.js b/lib/js/test/test-double-rendering.js
new file mode 100644
index 0000000..1790c1b
--- /dev/null
+++ b/lib/js/test/test-double-rendering.js
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+ /* jshint -W100 */
+
+/*
+ * JavaScript test suite for double constants inside
+ * DoubleConstantsTest.thrift. These tests will run against Normal (-gen js)
+ * Apache Thrift interfaces.
+ *
+ * To compile client code for this test use:
+ *      $ thrift -gen js DoubleConstantsTest.thrift
+ */
+
+// double assertion threshold
+const EPSILON = 0.0000001;
+
+// Work around for old API used by QUnitAdapter of jsTestDriver
+if (typeof QUnit.log == 'function') {
+  // When using real QUnit (fron PhantomJS) log failures to console
+  QUnit.log(function(details) {
+    if (!details.result) {
+      console.log('======== FAIL ========');
+      console.log('TestName: ' + details.name);
+      if (details.message) console.log(details.message);
+      console.log('Expected: ' + details.expected);
+      console.log('Actual  : ' + details.actual);
+      console.log('======================');
+    }
+  });
+}
+
+QUnit.module('Double rendering');
+
+  QUnit.test('Double (rendering)', function(assert) {
+    console.log('Double rendering test -- starts');
+    const EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308;
+    const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43;
+    assert.ok(
+        Math.abs(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT - DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS -
+            DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE -
+            DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, 'number');
+    const EXPECTED_DOUBLE_LIST =
+        [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,
+            9223372036854775816.43,-9223372036854775816.43];
+    assert.equal(DOUBLE_LIST_TEST.length, EXPECTED_DOUBLE_LIST.length);
+    for (let i = 0; i < EXPECTED_DOUBLE_LIST.length; ++i) {
+           assert.ok(Math.abs(EXPECTED_DOUBLE_LIST[i] - DOUBLE_LIST_TEST[i]) <= EPSILON);
+    }
+    console.log('Double rendering test -- ends');
+  });
+
diff --git a/lib/js/test/test-es6.html b/lib/js/test/test-es6.html
new file mode 100644
index 0000000..bf04901
--- /dev/null
+++ b/lib/js/test/test-es6.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Thrift Javascript Bindings: Unit Test</title>
+
+  <script src="build/js/thrift.js"         type="text/javascript" charset="utf-8"></script>
+  <script src="gen-js-es6/ThriftTest_types.js" type="text/javascript" charset="utf-8"></script>
+  <script src="gen-js-es6/ThriftTest.js"       type="text/javascript" charset="utf-8"></script>
+
+  <!-- jQuery -->
+  <script type="text/javascript" src="build/js/lib/jquery.js" charset="utf-8"></script>
+
+  <!-- QUnit Test framework-->
+  <script type="text/javascript" src="build/js/lib/qunit.js" charset="utf-8"></script>
+  <link rel="stylesheet" href="build/js/lib/qunit.css" type="text/css" media="screen" />
+
+  <!-- the Test Suite-->
+  <script>
+    const loc = window.location;
+    const ws_uri = ((loc.protocol === "https:") ? "wss://" : "ws://") +
+                   loc.hostname + ":" + loc.port + loc.pathname;
+    const transport = new Thrift.TWebSocketTransport(ws_uri);
+    const protocol  = new Thrift.Protocol(transport);
+    const client    = new ThriftTest.ThriftTestClient(protocol);
+    transport.open();
+  </script>
+  <script type="text/javascript" src="test-es6.js" charset="utf-8"></script>
+</head>
+<body>
+  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://github.com/apache/thrift/blob/master/test/ThriftTest.thrift">ThriftTest.thrift</a>)</h1>
+  <h2 id="qunit-banner"></h2>
+  <div id="qunit-testrunner-toolbar"></div>
+  <h2 id="qunit-userAgent"></h2>
+  <ol id="qunit-tests"><li><!-- get valid xhtml strict--></li></ol>
+  <!-- Uncomment this to check the validity. This significantly slows down the test.
+  <p>
+      <a href="http://validator.w3.org/check/referer"><img
+          src="http://www.w3.org/Icons/valid-xhtml10"
+          alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+  </p>
+  -->
+</body>
+</html>
diff --git a/lib/js/test/test-es6.js b/lib/js/test/test-es6.js
new file mode 100644
index 0000000..845171b
--- /dev/null
+++ b/lib/js/test/test-es6.js
@@ -0,0 +1,374 @@
+/*
+ * 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.
+ */
+ /* jshint -W100 */
+
+/*
+ * Fully Async JavaScript test suite for ThriftTest.thrift.
+ * These tests are designed to exercise the WebSocket transport
+ * (which is exclusively async).
+ *
+ * To compile client code for this test use:
+ *      $ thrift -gen js:es6 ThriftTest.thrift
+ */
+
+
+
+// all Languages in UTF-8
+
+const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
+
+function checkRecursively(assert, map1, map2) {
+  if (typeof map1 !== 'function' && typeof map2 !== 'function') {
+    if (!map1 || typeof map1 !== 'object') {
+        assert.equal(map1, map2);
+    } else {
+      for (var key in map1) {
+        checkRecursively(assert, map1[key], map2[key]);
+      }
+    }
+  }
+}
+
+QUnit.module('Base Types');
+
+  QUnit.test('Void', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testVoid().then(function(result) {
+      assert.equal(result, undefined);
+      done();
+    });
+  });
+
+  QUnit.test('String', function( assert ) {
+    assert.expect(3);
+    const done = assert.async(3);
+    client.testString('').then(function(result) {
+       assert.equal(result, '');
+       done();
+    });
+    client.testString(stringTest).then(function(result) {
+       assert.equal(result, stringTest);
+       done();
+    });
+    var specialCharacters = 'quote: \" backslash:' +
+          ' forwardslash-escaped: \/ ' +
+          ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
+          ' now-all-of-them-together: "\\\/\b\n\r\t' +
+          ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><';
+    client.testString(specialCharacters).then(function(result) {
+       assert.equal(result, specialCharacters);
+       done();
+    });
+  });
+
+  QUnit.test('Double', function( assert ) {
+    assert.expect(4);
+    const done = assert.async(4);
+    client.testDouble(0).then(function(result) {
+       assert.equal(result, 0);
+       done();
+    });
+    client.testDouble(-1).then(function(result) {
+       assert.equal(result, -1);
+       done();
+    });
+    client.testDouble(3.14).then(function(result) {
+       assert.equal(result, 3.14);
+       done();
+    });
+    client.testDouble(Math.pow(2, 60)).then(function(result) {
+       assert.equal(result, Math.pow(2, 60));
+       done();
+    });
+  });
+  // TODO: add testBinary()
+  QUnit.test('Byte', function( assert ) {
+    assert.expect(2);
+    const done = assert.async(2);
+    client.testByte(0).then(function(result) {
+       assert.equal(result, 0);
+       done();
+    });
+    client.testByte(0x01).then(function(result) {
+       assert.equal(result, 0x01);
+       done();
+    });
+  });
+  QUnit.test('I32', function( assert ) {
+    assert.expect(3);
+    const done = assert.async(3);
+    client.testI32(0).then(function(result) {
+       assert.equal(result, 0);
+       done();
+    });
+    client.testI32(Math.pow(2, 30)).then(function(result) {
+       assert.equal(result, Math.pow(2, 30));
+       done();
+    });
+    client.testI32(-Math.pow(2, 30)).then(function(result) {
+       assert.equal(result, -Math.pow(2, 30));
+       done();
+    });
+  });
+  QUnit.test('I64', function( assert ) {
+    assert.expect(3);
+    const done = assert.async(3);
+    client.testI64(0).then(function(result) {
+       assert.equal(result, 0);
+       done();
+    });
+    //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
+    client.testI64(Math.pow(2, 52)).then(function(result) {
+       assert.equal(result, Math.pow(2, 52));
+       done();
+    });
+    client.testI64(-Math.pow(2, 52)).then(function(result) {
+       assert.equal(result, -Math.pow(2, 52));
+       done();
+    });
+  });
+
+
+QUnit.module('Structured Types');
+
+  QUnit.test('Struct', function( assert ) {
+    assert.expect(5);
+    const done = assert.async();
+    var structTestInput = new ThriftTest.Xtruct();
+    structTestInput.string_thing = 'worked';
+    structTestInput.byte_thing = 0x01;
+    structTestInput.i32_thing = Math.pow(2, 30);
+    //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
+    structTestInput.i64_thing = Math.pow(2, 52);
+
+    client.testStruct(structTestInput).then(function(result) {
+      assert.equal(result.string_thing, structTestInput.string_thing);
+      assert.equal(result.byte_thing, structTestInput.byte_thing);
+      assert.equal(result.i32_thing, structTestInput.i32_thing);
+      assert.equal(result.i64_thing, structTestInput.i64_thing);
+      assert.equal(JSON.stringify(result), JSON.stringify(structTestInput));
+      done();
+    });
+  });
+
+  QUnit.test('Nest', function( assert ) {
+    assert.expect(7);
+    const done = assert.async();
+    var xtrTestInput = new ThriftTest.Xtruct();
+    xtrTestInput.string_thing = 'worked';
+    xtrTestInput.byte_thing = 0x01;
+    xtrTestInput.i32_thing = Math.pow(2, 30);
+    //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
+    xtrTestInput.i64_thing = Math.pow(2, 52);
+
+    var nestTestInput = new ThriftTest.Xtruct2();
+    nestTestInput.byte_thing = 0x02;
+    nestTestInput.struct_thing = xtrTestInput;
+    nestTestInput.i32_thing = Math.pow(2, 15);
+
+    client.testNest(nestTestInput).then(function(result) {
+      assert.equal(result.byte_thing, nestTestInput.byte_thing);
+      assert.equal(result.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
+      assert.equal(result.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
+      assert.equal(result.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
+      assert.equal(result.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing);
+      assert.equal(result.i32_thing, nestTestInput.i32_thing);
+      assert.equal(JSON.stringify(result), JSON.stringify(nestTestInput));
+      done();
+    });
+  });
+
+  QUnit.test('Map', function( assert ) {
+    assert.expect(3);
+    const done = assert.async();
+    var mapTestInput = {7: 77, 8: 88, 9: 99};
+
+    client.testMap(mapTestInput).then(function(result) {
+      for (var key in result) {
+        assert.equal(result[key], mapTestInput[key]);
+      }
+      done();
+    });
+  });
+
+  QUnit.test('StringMap', function( assert ) {
+    assert.expect(6);
+    const done = assert.async();
+    var mapTestInput = {
+      'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key',
+      'longValue': stringTest, stringTest: 'long key'
+    };
+
+    client.testStringMap(mapTestInput).then(function(result) {
+      for (var key in result) {
+        assert.equal(result[key], mapTestInput[key]);
+      }
+      done();
+    });
+  });
+
+  QUnit.test('Set', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    var setTestInput = [1, 2, 3];
+    client.testSet(setTestInput).then(function(result) {
+      assert.ok(result, setTestInput);
+      done();
+    });
+  });
+
+  QUnit.test('List', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    var listTestInput = [1, 2, 3];
+    client.testList(listTestInput).then(function(result) {
+      assert.ok(result, listTestInput);
+      done();
+    });
+  });
+
+  QUnit.test('Enum', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testEnum(ThriftTest.Numberz.ONE).then(function(result) {
+      assert.equal(result, ThriftTest.Numberz.ONE);
+      done();
+    });
+  });
+
+  QUnit.test('TypeDef', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testTypedef(69).then(function(result) {
+      assert.equal(result, 69);
+      done();
+    });
+  });
+
+
+QUnit.module('deeper!');
+
+  QUnit.test('MapMap', function( assert ) {
+    assert.expect(16);
+    const done = assert.async();
+    var mapMapTestExpectedResult = {
+      '4': {'1': 1, '2': 2, '3': 3, '4': 4},
+      '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1}
+    };
+
+    client.testMapMap(1).then(function(result) {
+      for (var key in result) {
+        for (var key2 in result[key]) {
+          assert.equal(result[key][key2], mapMapTestExpectedResult[key][key2]);
+        }
+      }
+      checkRecursively(assert, result, mapMapTestExpectedResult);
+      done();
+    });
+  });
+
+
+QUnit.module('Exception');
+
+  QUnit.test('Xception', function( assert ) {
+    assert.expect(2);
+    const done = assert.async();
+    client.testException('Xception').then(function(res) {
+      assert.ok(false);
+    }).catch(function(e) {
+
+      console.log(`Exception exception e`);
+      console.log(e);
+      console.log(JSON.stringify(e, null, 2));
+
+      assert.equal(e.errorCode, 1001);
+      assert.equal(e.message, 'Xception');
+      done();
+    });
+  });
+
+  QUnit.test('no Exception', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testException('no Exception').then(function(e) {
+      assert.ok(!e);
+      done();
+    });
+  });
+
+QUnit.module('Insanity');
+
+  QUnit.test('testInsanity', function( assert ) {
+    assert.expect(24);
+    const done = assert.async();
+    var insanity = {
+      '1': {
+        '2': {
+          'userMap': { '5': 5, '8': 8 },
+          'xtructs': [{
+              'string_thing': 'Goodbye4',
+              'byte_thing': 4,
+              'i32_thing': 4,
+              'i64_thing': 4
+            },
+            {
+              'string_thing': 'Hello2',
+              'byte_thing': 2,
+              'i32_thing': 2,
+              'i64_thing': 2
+            }
+          ]
+        },
+        '3': {
+          'userMap': { '5': 5, '8': 8 },
+          'xtructs': [{
+              'string_thing': 'Goodbye4',
+              'byte_thing': 4,
+              'i32_thing': 4,
+              'i64_thing': 4
+            },
+            {
+              'string_thing': 'Hello2',
+              'byte_thing': 2,
+              'i32_thing': 2,
+              'i64_thing': 2
+            }
+          ]
+        }
+      },
+      '2': { '6': { 'userMap': null, 'xtructs': null } }
+    };
+    client.testInsanity(new ThriftTest.Insanity()).then(function(res) {
+      assert.ok(res, JSON.stringify(res));
+      assert.ok(insanity, JSON.stringify(insanity));
+      checkRecursively(assert, res, insanity);
+      done();
+    });
+  });
+
+QUnit.module('Oneway');
+  QUnit.test('testOneway', function( assert ) {
+    assert.expect(1);
+    const done = assert.async();
+    client.testOneway(1).then(function(result) {
+      assert.equal(result, undefined);
+      done();
+    });
+  });
diff --git a/lib/js/test/test-jq.js b/lib/js/test/test-jq.js
index d8649a0..f62bb95 100644
--- a/lib/js/test/test-jq.js
+++ b/lib/js/test/test-jq.js
@@ -33,19 +33,18 @@
 //////////////////////////////////
 //jQuery asynchronous tests
 jQuery.ajaxSetup({ timeout: 0 });
-$(document).ajaxError(function() { QUnit.start(); });
 
-module('jQ Async Manual');
+QUnit.module('jQ Async Manual');
 
-  test('testI32', function() {
-    expect(2);
-    QUnit.stop();
+  QUnit.test('testI32', function(assert) {
+    assert.expect(2);
+    const done = assert.async(2);
 
-    var transport = new Thrift.Transport();
-    var protocol = new Thrift.Protocol(transport);
-    var client = new ThriftTest.ThriftTestClient(protocol);
+    const transport = new Thrift.Transport();
+    const protocol = new Thrift.Protocol(transport);
+    const client = new ThriftTest.ThriftTestClient(protocol);
 
-    var jqxhr = jQuery.ajax({
+    const jqxhr = jQuery.ajax({
       url: '/service',
       data: client.send_testI32(Math.pow(-2, 31)),
       type: 'POST',
@@ -53,23 +52,24 @@
       dataType: 'text',
       success: function(res) {
         transport.setRecvBuffer(res);
-        equal(client.recv_testI32(), Math.pow(-2, 31));
+        assert.equal(client.recv_testI32(), Math.pow(-2, 31));
+        done();
       },
-      error: function() { ok(false); },
+      error: function() { assert.ok(false); },
       complete: function() {
-        ok(true);
-        QUnit.start();
+        assert.ok(true);
+        done();
       }
     });
   });
 
-  test('testI64', function() {
-    expect(2);
-    QUnit.stop();
+  QUnit.test('testI64', function(assert) {
+    assert.expect(2);
+    const done = assert.async(2);
 
-    var transport = new Thrift.Transport();
-    var protocol = new Thrift.Protocol(transport);
-    var client = new ThriftTest.ThriftTestClient(protocol);
+    const transport = new Thrift.Transport();
+    const protocol = new Thrift.Protocol(transport);
+    const client = new ThriftTest.ThriftTestClient(protocol);
 
     jQuery.ajax({
       url: '/service',
@@ -81,78 +81,79 @@
       success: function(res) {
         transport.setRecvBuffer(res);
         //This is usually 2^61 but JS cannot represent anything over 2^52 accurately
-        equal(client.recv_testI64(), Math.pow(-2, 52));
+        assert.equal(client.recv_testI64(), Math.pow(-2, 52));
+        done();
       },
-      error: function() { ok(false); },
+      error: function() { assert.ok(false); },
       complete: function() {
-        ok(true);
-        QUnit.start();
+        assert.ok(true);
+        done();
       }
     });
   });
 
 
-module('jQ Async');
-  test('I32', function() {
-    expect(3);
+QUnit.module('jQ Async');
+  QUnit.test('I32', function(assert) {
+    assert.expect(3);
 
-    QUnit.stop();
+    const done = assert.async(3);
     client.testI32(Math.pow(2, 30), function(result) {
-      equal(result, Math.pow(2, 30));
-      QUnit.start();
+      assert.equal(result, Math.pow(2, 30));
+      done();
     });
 
-    QUnit.stop();
-    var jqxhr = client.testI32(Math.pow(-2, 31), function(result) {
-      equal(result, Math.pow(-2, 31));
+    const jqxhr = client.testI32(Math.pow(-2, 31), function(result) {
+      assert.equal(result, Math.pow(-2, 31));
+      done();
     });
 
     jqxhr.success(function(result) {
-      equal(result, Math.pow(-2, 31));
-      QUnit.start();
+      assert.equal(result, Math.pow(-2, 31));
+      done();
     });
   });
 
-  test('I64', function() {
-    expect(4);
+  QUnit.test('I64', function(assert) {
+    assert.expect(4);
 
-    QUnit.stop();
+    const done = assert.async(4);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     client.testI64(Math.pow(2, 52), function(result) {
-      equal(result, Math.pow(2, 52));
-      QUnit.start();
+      assert.equal(result, Math.pow(2, 52));
+      done();
     });
 
-    QUnit.stop();
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     client.testI64(Math.pow(-2, 52), function(result) {
-      equal(result, Math.pow(-2, 52));
+      assert.equal(result, Math.pow(-2, 52));
+      done();
     })
-    .error(function(xhr, status, e) { ok(false, e.message); })
+    .error(function(xhr, status, e) { assert.ok(false, e.message); })
     .success(function(result) {
       //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
-      equal(result, Math.pow(-2, 52));
+      assert.equal(result, Math.pow(-2, 52));
+      done();
     })
     .complete(function() {
-      ok(true);
-      QUnit.start();
+      assert.ok(true);
+      done();
     });
   });
 
-  test('Xception', function() {
-    expect(2);
+  QUnit.test('Xception', function(assert) {
+    assert.expect(2);
 
-    QUnit.stop();
+    const done = assert.async(2);
 
-    var dfd = client.testException('Xception', function(result) {
-      ok(false);
-      QUnit.start();
+    const dfd = client.testException('Xception', function(result) {
+      assert.ok(false);
+      done();
     })
     .error(function(xhr, status, e) {
-      equal(e.errorCode, 1001);
-      equal(e.message, 'Xception');
-      //QUnit.start();
-      //Note start is not required here because:
-      //$(document).ajaxError( function() { QUnit.start(); } );
+      assert.equal(e.errorCode, 1001);
+      assert.equal(e.message, 'Xception');
+      done();
+      $(document).ajaxError( function() { done(); } );
     });
   });
diff --git a/lib/js/test/test-nojq.html b/lib/js/test/test-nojq.html
index 541bffe..408424e 100644
--- a/lib/js/test/test-nojq.html
+++ b/lib/js/test/test-nojq.html
@@ -29,15 +29,15 @@
   <!-- QUnit Test framework-->
   <script type="text/javascript" src="build/js/lib/qunit.js" charset="utf-8"></script>
   <link rel="stylesheet" href="build/js/lib/qunit.css" type="text/css" media="screen" />
-  
+
   <!-- the Test Suite-->
   <script type="text/javascript" src="test.js" charset="utf-8"></script>
   <script type="text/javascript" src="test-nojq.js" charset="utf-8"></script>
 </head>
 <body>
-  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=test/ThriftTest.thrift;hb=HEAD">ThriftTest.thrift</a>)</h1>
+  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://github.com/apache/thrift/blob/master/test/ThriftTest.thrift">ThriftTest.thrift</a>)</h1>
   <h2 id="qunit-banner"></h2>
-  <div id="qunit-testrunner-toolbar"></div> 
+  <div id="qunit-testrunner-toolbar"></div>
   <h2 id="qunit-userAgent"></h2>
   <ol id="qunit-tests"><li><!-- get valid xhtml strict--></li></ol>
   <!-- Uncomment this to check the validity. This significantly slows down the test.
diff --git a/lib/js/test/test-nojq.js b/lib/js/test/test-nojq.js
index c4f3cf7..2b801d2 100644
--- a/lib/js/test/test-nojq.js
+++ b/lib/js/test/test-nojq.js
@@ -33,17 +33,16 @@
 //////////////////////////////////
 //Async exception tests
 
-module('NojQ Async');
+QUnit.module('NojQ Async');
 
-  test('Xception', function() {
-    expect(2);
-
-    QUnit.stop();
+QUnit.test('Xception', function(assert) {
+    assert.expect(2);
+    const done = assert.async();
 
     client.testException('Xception', function(result) {
-      equal(result.errorCode, 1001);
-      equal(result.message, 'Xception');
-      QUnit.start();
+      assert.equal(result.errorCode, 1001);
+      assert.equal(result.message, 'Xception');
+      done();
     });
   });
 
diff --git a/lib/js/test/test.html b/lib/js/test/test.html
index edec3a3..8b67014 100755
--- a/lib/js/test/test.html
+++ b/lib/js/test/test.html
@@ -23,8 +23,8 @@
   <title>Thrift Javascript Bindings: Unit Test</title>
 
   <script src="build/js/thrift.js"         type="text/javascript" charset="utf-8"></script>
-  <script src="gen-js/ThriftTest_types.js" type="text/javascript" charset="utf-8"></script>
-  <script src="gen-js/ThriftTest.js"       type="text/javascript" charset="utf-8"></script>
+  <script src="gen-js-jquery/ThriftTest_types.js" type="text/javascript" charset="utf-8"></script>
+  <script src="gen-js-jquery/ThriftTest.js"       type="text/javascript" charset="utf-8"></script>
 
   <!-- jQuery -->
   <script type="text/javascript" src="build/js/lib/jquery.js" charset="utf-8"></script>
@@ -34,16 +34,11 @@
   <link rel="stylesheet" href="build/js/lib/qunit.css" type="text/css" media="screen" />
 
   <!-- the Test Suite-->
-  <script>
-    var transport = new Thrift.Transport("/service");
-    var protocol  = new Thrift.Protocol(transport);
-    var client    = new ThriftTest.ThriftTestClient(protocol);
-  </script>
   <script type="text/javascript" src="test.js" charset="utf-8"></script>
   <script type="text/javascript" src="test-jq.js" charset="utf-8"></script>
 </head>
 <body>
-  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=test/ThriftTest.thrift;hb=HEAD">ThriftTest.thrift</a>)</h1>
+  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://github.com/apache/thrift/blob/master/test/ThriftTest.thrift">ThriftTest.thrift</a>)</h1>
   <h2 id="qunit-banner"></h2>
   <div id="qunit-testrunner-toolbar"></div>
   <h2 id="qunit-userAgent"></h2>
diff --git a/lib/js/test/test.js b/lib/js/test/test.js
index e3b8d51..a86a509 100755
--- a/lib/js/test/test.js
+++ b/lib/js/test/test.js
@@ -47,9 +47,9 @@
  * ++ test-jq.js for "-gen js:jquery" only tests
  */
 
-var transport = new Thrift.Transport('/service');
-var protocol = new Thrift.Protocol(transport);
-var client = new ThriftTest.ThriftTestClient(protocol);
+const transport = new Thrift.Transport('/service');
+const protocol = new Thrift.Protocol(transport);
+const client = new ThriftTest.ThriftTestClient(protocol);
 
 // Work around for old API used by QUnitAdapter of jsTestDriver
 if (typeof QUnit.log == 'function') {
@@ -67,170 +67,170 @@
 }
 
 // all Languages in UTF-8
-var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
+const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
 
-function checkRecursively(map1, map2) {
+function checkRecursively(assert, map1, map2) {
   if (typeof map1 !== 'function' && typeof map2 !== 'function') {
     if (!map1 || typeof map1 !== 'object') {
-        equal(map1, map2);
+        assert.equal(map1, map2);
     } else {
-      for (var key in map1) {
-        checkRecursively(map1[key], map2[key]);
+      for (let key in map1) {
+        checkRecursively(assert, map1[key], map2[key]);
       }
     }
   }
 }
 
-module('Base Types');
+QUnit.module('Base Types');
 
-  test('Void', function() {
-    equal(client.testVoid(), undefined);
+  QUnit.test('Void', function(assert) {
+    assert.equal(client.testVoid(), undefined);
   });
-  test('Binary (String)', function() {
-    var binary = '';
-    for (var v = 255; v >= 0; --v) {
+  QUnit.test('Binary (String)', function(assert) {
+    let binary = '';
+    for (let v = 255; v >= 0; --v) {
       binary += String.fromCharCode(v);
     }
-    equal(client.testBinary(binary), binary);
+    assert.equal(client.testBinary(binary), binary);
   });
-  test('Binary (Uint8Array)', function() {
-    var binary = '';
-    for (var v = 255; v >= 0; --v) {
+  QUnit.test('Binary (Uint8Array)', function(assert) {
+    let binary = '';
+    for (let v = 255; v >= 0; --v) {
       binary += String.fromCharCode(v);
     }
-    var arr = new Uint8Array(binary.length);
-    for (var i = 0; i < binary.length; ++i) {
+    const arr = new Uint8Array(binary.length);
+    for (let i = 0; i < binary.length; ++i) {
       arr[i] = binary[i].charCodeAt();
     }
-    equal(client.testBinary(arr), binary);
+    assert.equal(client.testBinary(arr), binary);
   });
-  test('String', function() {
-    equal(client.testString(''), '');
-    equal(client.testString(stringTest), stringTest);
+  QUnit.test('String', function(assert) {
+    assert.equal(client.testString(''), '');
+    assert.equal(client.testString(stringTest), stringTest);
 
-    var specialCharacters = 'quote: \" backslash:' +
+    const specialCharacters = 'quote: \" backslash:' +
           ' forwardslash-escaped: \/ ' +
           ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
           ' now-all-of-them-together: "\\\/\b\n\r\t' +
           ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><';
-    equal(client.testString(specialCharacters), specialCharacters);
+    assert.equal(client.testString(specialCharacters), specialCharacters);
   });
-  test('Double', function() {
-    equal(client.testDouble(0), 0);
-    equal(client.testDouble(-1), -1);
-    equal(client.testDouble(3.14), 3.14);
-    equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60));
+  QUnit.test('Double', function(assert) {
+    assert.equal(client.testDouble(0), 0);
+    assert.equal(client.testDouble(-1), -1);
+    assert.equal(client.testDouble(3.14), 3.14);
+    assert.equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60));
   });
-  test('Byte', function() {
-    equal(client.testByte(0), 0);
-    equal(client.testByte(0x01), 0x01);
+  QUnit.test('Byte', function(assert) {
+    assert.equal(client.testByte(0), 0);
+    assert.equal(client.testByte(0x01), 0x01);
   });
-  test('I32', function() {
-    equal(client.testI32(0), 0);
-    equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30));
-    equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30));
+  QUnit.test('I32', function(assert) {
+    assert.equal(client.testI32(0), 0);
+    assert.equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30));
+    assert.equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30));
   });
-  test('I64', function() {
-    equal(client.testI64(0), 0);
+  QUnit.test('I64', function(assert) {
+    assert.equal(client.testI64(0), 0);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
-    equal(client.testI64(Math.pow(2, 52)), Math.pow(2, 52));
-    equal(client.testI64(-Math.pow(2, 52)), -Math.pow(2, 52));
+    assert.equal(client.testI64(Math.pow(2, 52)), Math.pow(2, 52));
+    assert.equal(client.testI64(-Math.pow(2, 52)), -Math.pow(2, 52));
   });
 
 
-module('Structured Types');
+QUnit.module('Structured Types');
 
-  test('Struct', function() {
-    var structTestInput = new ThriftTest.Xtruct();
+  QUnit.test('Struct', function(assert) {
+    const structTestInput = new ThriftTest.Xtruct();
     structTestInput.string_thing = 'worked';
     structTestInput.byte_thing = 0x01;
     structTestInput.i32_thing = Math.pow(2, 30);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     structTestInput.i64_thing = Math.pow(2, 52);
 
-    var structTestOutput = client.testStruct(structTestInput);
+    const structTestOutput = client.testStruct(structTestInput);
 
-    equal(structTestOutput.string_thing, structTestInput.string_thing);
-    equal(structTestOutput.byte_thing, structTestInput.byte_thing);
-    equal(structTestOutput.i32_thing, structTestInput.i32_thing);
-    equal(structTestOutput.i64_thing, structTestInput.i64_thing);
+    assert.equal(structTestOutput.string_thing, structTestInput.string_thing);
+    assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing);
+    assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing);
+    assert.equal(structTestOutput.i64_thing, structTestInput.i64_thing);
 
-    equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput));
+    assert.equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput));
   });
 
-  test('Nest', function() {
-    var xtrTestInput = new ThriftTest.Xtruct();
+  QUnit.test('Nest', function(assert) {
+    const xtrTestInput = new ThriftTest.Xtruct();
     xtrTestInput.string_thing = 'worked';
     xtrTestInput.byte_thing = 0x01;
     xtrTestInput.i32_thing = Math.pow(2, 30);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     xtrTestInput.i64_thing = Math.pow(2, 52);
 
-    var nestTestInput = new ThriftTest.Xtruct2();
+    const nestTestInput = new ThriftTest.Xtruct2();
     nestTestInput.byte_thing = 0x02;
     nestTestInput.struct_thing = xtrTestInput;
     nestTestInput.i32_thing = Math.pow(2, 15);
 
-    var nestTestOutput = client.testNest(nestTestInput);
+    const nestTestOutput = client.testNest(nestTestInput);
 
-    equal(nestTestOutput.byte_thing, nestTestInput.byte_thing);
-    equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
-    equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
-    equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
-    equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing);
-    equal(nestTestOutput.i32_thing, nestTestInput.i32_thing);
+    assert.equal(nestTestOutput.byte_thing, nestTestInput.byte_thing);
+    assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
+    assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
+    assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
+    assert.equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing);
+    assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing);
 
-    equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput));
+    assert.equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput));
   });
 
-  test('Map', function() {
-    var mapTestInput = {7: 77, 8: 88, 9: 99};
+  QUnit.test('Map', function(assert) {
+    const mapTestInput = {7: 77, 8: 88, 9: 99};
 
-    var mapTestOutput = client.testMap(mapTestInput);
+    const mapTestOutput = client.testMap(mapTestInput);
 
-    for (var key in mapTestOutput) {
-      equal(mapTestOutput[key], mapTestInput[key]);
+    for (let key in mapTestOutput) {
+      assert.equal(mapTestOutput[key], mapTestInput[key]);
     }
   });
 
-  test('StringMap', function() {
-    var mapTestInput = {
+  QUnit.test('StringMap', function(assert) {
+    const mapTestInput = {
       'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key',
       'longValue': stringTest, stringTest: 'long key'
     };
 
-    var mapTestOutput = client.testStringMap(mapTestInput);
+    const mapTestOutput = client.testStringMap(mapTestInput);
 
-    for (var key in mapTestOutput) {
-      equal(mapTestOutput[key], mapTestInput[key]);
+    for (let key in mapTestOutput) {
+      assert.equal(mapTestOutput[key], mapTestInput[key]);
     }
   });
 
-  test('Set', function() {
-    var setTestInput = [1, 2, 3];
-    ok(client.testSet(setTestInput), setTestInput);
+  QUnit.test('Set', function(assert) {
+    const setTestInput = [1, 2, 3];
+    assert.ok(client.testSet(setTestInput), setTestInput);
   });
 
-  test('List', function() {
-    var listTestInput = [1, 2, 3];
-    ok(client.testList(listTestInput), listTestInput);
+  QUnit.test('List', function(assert) {
+    const listTestInput = [1, 2, 3];
+    assert.ok(client.testList(listTestInput), listTestInput);
   });
 
-  test('Enum', function() {
-    equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE);
+  QUnit.test('Enum', function(assert) {
+    assert.equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE);
   });
 
-  test('TypeDef', function() {
-    equal(client.testTypedef(69), 69);
+  QUnit.test('TypeDef', function(assert) {
+    assert.equal(client.testTypedef(69), 69);
   });
 
-  test('Skip', function() {
-    var structTestInput = new ThriftTest.Xtruct();
-    var modifiedClient = new ThriftTest.ThriftTestClient(protocol);
+  QUnit.test('Skip', function(assert) {
+    const structTestInput = new ThriftTest.Xtruct();
+    const modifiedClient = new ThriftTest.ThriftTestClient(protocol);
 
     modifiedClient.recv_testStruct = function() {
-      var input = modifiedClient.input;
-      var xtruct3 = new ThriftTest.Xtruct3();
+      const input = modifiedClient.input;
+      const xtruct3 = new ThriftTest.Xtruct3();
 
       input.readMessageBegin();
       input.readStructBegin();
@@ -254,74 +254,79 @@
     structTestInput.i32_thing = Math.pow(2, 30);
     structTestInput.i64_thing = Math.pow(2, 52);
 
-    var structTestOutput = modifiedClient.testStruct(structTestInput);
+    const structTestOutput = modifiedClient.testStruct(structTestInput);
 
-    equal(structTestOutput instanceof ThriftTest.Xtruct3, true);
-    equal(structTestOutput.string_thing, structTestInput.string_thing);
-    equal(structTestOutput.changed, null);
-    equal(structTestOutput.i32_thing, structTestInput.i32_thing);
-    equal(structTestOutput.i64_thing, structTestInput.i64_thing);
+    assert.equal(structTestOutput instanceof ThriftTest.Xtruct3, true);
+    assert.equal(structTestOutput.string_thing, structTestInput.string_thing);
+    assert.equal(structTestOutput.changed, null);
+    assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing);
+    assert.equal(structTestOutput.i64_thing, structTestInput.i64_thing);
   });
 
 
-module('deeper!');
+QUnit.module('deeper!');
 
-  test('MapMap', function() {
-    var mapMapTestExpectedResult = {
+  QUnit.test('MapMap', function(assert) {
+    const mapMapTestExpectedResult = {
       '4': {'1': 1, '2': 2, '3': 3, '4': 4},
       '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1}
     };
 
-    var mapMapTestOutput = client.testMapMap(1);
+    const mapMapTestOutput = client.testMapMap(1);
 
 
-    for (var key in mapMapTestOutput) {
-      for (var key2 in mapMapTestOutput[key]) {
-        equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]);
+    for (let key in mapMapTestOutput) {
+      for (let key2 in mapMapTestOutput[key]) {
+        assert.equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]);
       }
     }
 
-    checkRecursively(mapMapTestOutput, mapMapTestExpectedResult);
+    checkRecursively(assert, mapMapTestOutput, mapMapTestExpectedResult);
   });
 
 
-module('Exception');
+QUnit.module('Exception');
 
-  test('Xception', function() {
-    expect(2);
+  QUnit.test('Xception', function(assert) {
+    assert.expect(2);
+    const done = assert.async();
     try {
       client.testException('Xception');
+      assert.ok(false);
     }catch (e) {
-      equal(e.errorCode, 1001);
-      equal(e.message, 'Xception');
+      assert.equal(e.errorCode, 1001);
+      assert.equal(e.message, 'Xception');
+      done();
     }
   });
 
-  test('no Exception', 0, function() {
+  QUnit.test('no Exception', function(assert) {
+    assert.expect(1);
     try {
       client.testException('no Exception');
+      assert.ok(true);
     }catch (e) {
-      ok(false);
+      assert.ok(false);
     }
   });
 
-  test('TException', function() {
+  QUnit.test('TException', function(assert) {
     //ThriftTest does not list TException as a legal exception so it will
     // generate an exception on the server that does not propagate back to
     // the client. This test has been modified to equate to "no exception"
-    expect(1);
+    assert.expect(1);
     try {
       client.testException('TException');
     } catch (e) {
-      //ok(false);
+      //assert.ok(false);
     }
-    ok(true);
+    assert.ok(true);
   });
 
 
-module('Insanity');
+QUnit.module('Insanity');
 
-  var crazy = {
+  const crazy = {
     'userMap': { '5': 5, '8': 8 },
     'xtructs': [{
       'string_thing': 'Goodbye4',
@@ -336,77 +341,75 @@
       'i64_thing': 2
     }]
   };
-  test('testInsanity', function() {
-    var insanity = {
+  QUnit.test('testInsanity', function(assert) {
+    const insanity = {
       '1': {
         '2': crazy,
         '3': crazy
       },
       '2': { '6': { 'userMap': null, 'xtructs': null } }
     };
-    var res = client.testInsanity(new ThriftTest.Insanity(crazy));
-    ok(res, JSON.stringify(res));
-    ok(insanity, JSON.stringify(insanity));
+    const res = client.testInsanity(new ThriftTest.Insanity(crazy));
+    assert.ok(res, JSON.stringify(res));
+    assert.ok(insanity, JSON.stringify(insanity));
 
-    checkRecursively(res, insanity);
+    checkRecursively(assert, res, insanity);
   });
 
 
 //////////////////////////////////
 //Run same tests asynchronously
 
-module('Async');
+QUnit.module('Async');
 
-  test('Double', function() {
-    expect(1);
+  QUnit.test('Double', function(assert) {
+    assert.expect(1);
 
-    QUnit.stop();
+    const done = assert.async();
     client.testDouble(3.14159265, function(result) {
-      equal(result, 3.14159265);
-      QUnit.start();
+      assert.equal(result, 3.14159265);
+      done();
     });
   });
 
-  test('Byte', function() {
-    expect(1);
+  QUnit.test('Byte', function(assert) {
+    assert.expect(1);
 
-    QUnit.stop();
+    const done = assert.async();
     client.testByte(0x01, function(result) {
-      equal(result, 0x01);
-      QUnit.start();
+      assert.equal(result, 0x01);
+      done();
     });
   });
 
-  test('I32', function() {
-    expect(2);
+  QUnit.test('I32', function(assert) {
+    assert.expect(2);
 
-    QUnit.stop();
+    const done = assert.async(2);
     client.testI32(Math.pow(2, 30), function(result) {
-      equal(result, Math.pow(2, 30));
-      QUnit.start();
+      assert.equal(result, Math.pow(2, 30));
+      done();
     });
 
-    QUnit.stop();
     client.testI32(Math.pow(-2, 31), function(result) {
-      equal(result, Math.pow(-2, 31));
-      QUnit.start();
+      assert.equal(result, Math.pow(-2, 31));
+      done();
     });
   });
 
-  test('I64', function() {
-    expect(2);
+  QUnit.test('I64', function(assert) {
+    assert.expect(2);
 
-    QUnit.stop();
+    const done = assert.async(2);
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     client.testI64(Math.pow(2, 52), function(result) {
-      equal(result, Math.pow(2, 52));
-      QUnit.start();
+      assert.equal(result, Math.pow(2, 52));
+      done();
     });
 
-    QUnit.stop();
     //This is usually 2^60 but JS cannot represent anything over 2^52 accurately
     client.testI64(Math.pow(-2, 52), function(result) {
-      equal(result, Math.pow(-2, 52));
-      QUnit.start();
+      assert.equal(result, Math.pow(-2, 52));
+      done();
     });
   });
diff --git a/lib/js/test/test_handler.js b/lib/js/test/test_handler.js
index 496b5e0..af5f7bd 100644
--- a/lib/js/test/test_handler.js
+++ b/lib/js/test/test_handler.js
@@ -20,10 +20,12 @@
 //This is the server side Node test handler for the standard
 //  Apache Thrift test service.
 
-var ttypes = require('./gen-nodejs/ThriftTest_types');
-var TException = require('../../nodejs/lib/thrift').TException;
+const es6Mode = process.argv.includes('--es6');
+const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs';
+const ttypes = require(`./${genFolder}/ThriftTest_types`);
+const TException = require('../../nodejs/lib/thrift').TException;
 
-var ThriftTestHandler = exports.ThriftTestHandler = {
+exports.ThriftTestHandler = {
   testVoid: function(result) {
     console.log('testVoid()');
     result(null);
@@ -99,10 +101,10 @@
   testMapMap: function(hello, result) {
     console.log('testMapMap(' + hello + ')');
 
-    var mapmap = [];
-    var pos = [];
-    var neg = [];
-    for (var i = 1; i < 5; i++) {
+    const mapmap = [];
+    const pos = [];
+    const neg = [];
+    for (let i = 1; i < 5; i++) {
       pos[i] = i;
       neg[-i] = -i;
     }
@@ -116,34 +118,34 @@
     console.log(argument);
     console.log(')');
 
-    var hello = new ttypes.Xtruct();
+    const hello = new ttypes.Xtruct();
     hello.string_thing = 'Hello2';
     hello.byte_thing = 2;
     hello.i32_thing = 2;
     hello.i64_thing = 2;
 
-    var goodbye = new ttypes.Xtruct();
+    const goodbye = new ttypes.Xtruct();
     goodbye.string_thing = 'Goodbye4';
     goodbye.byte_thing = 4;
     goodbye.i32_thing = 4;
     goodbye.i64_thing = 4;
 
-    var crazy = new ttypes.Insanity();
+    const crazy = new ttypes.Insanity();
     crazy.userMap = [];
     crazy.userMap[ttypes.Numberz.EIGHT] = 8;
     crazy.userMap[ttypes.Numberz.FIVE] = 5;
     crazy.xtructs = [goodbye, hello];
 
-    var first_map = [];
-    var second_map = [];
+    const first_map = [];
+    const second_map = [];
 
     first_map[ttypes.Numberz.TWO] = crazy;
     first_map[ttypes.Numberz.THREE] = crazy;
 
-    var looney = new ttypes.Insanity();
+    const looney = new ttypes.Insanity();
     second_map[ttypes.Numberz.SIX] = looney;
 
-    var insane = [];
+    const insane = [];
     insane[1] = first_map;
     insane[2] = second_map;
 
@@ -154,7 +156,7 @@
   testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) {
     console.log('testMulti()');
 
-    var hello = new ttypes.Xtruct();
+    const hello = new ttypes.Xtruct();
     hello.string_thing = 'Hello2';
     hello.byte_thing = arg0;
     hello.i32_thing = arg1;
@@ -164,7 +166,7 @@
   testException: function(arg, result) {
     console.log('testException(' + arg + ')');
     if (arg === 'Xception') {
-      var x = new ttypes.Xception();
+      const x = new ttypes.Xception();
       x.errorCode = 1001;
       x.message = arg;
       result(x);
@@ -177,19 +179,19 @@
   testMultiException: function(arg0, arg1, result) {
     console.log('testMultiException(' + arg0 + ', ' + arg1 + ')');
     if (arg0 === ('Xception')) {
-      var x = new ttypes.Xception();
+      const x = new ttypes.Xception();
       x.errorCode = 1001;
       x.message = 'This is an Xception';
       result(x);
     } else if (arg0 === ('Xception2')) {
-      var x2 = new ttypes.Xception2();
+      const x2 = new ttypes.Xception2();
       x2.errorCode = 2002;
       x2.struct_thing = new ttypes.Xtruct();
       x2.struct_thing.string_thing = 'This is an Xception2';
       result(x2);
     }
 
-    var res = new ttypes.Xtruct();
+    const res = new ttypes.Xtruct();
     res.string_thing = arg1;
     result(null, res);
   },
diff --git a/lib/js/test/testws.html b/lib/js/test/testws.html
index f99a146..184500f 100644
--- a/lib/js/test/testws.html
+++ b/lib/js/test/testws.html
@@ -35,18 +35,18 @@
 
   <!-- the Test Suite-->
   <script>
-    var loc = window.location;
-    var ws_uri = ((loc.protocol === "https:") ? "wss://" : "ws://") +
+    const loc = window.location;
+    const ws_uri = ((loc.protocol === "https:") ? "wss://" : "ws://") +
                    loc.hostname + ":" + loc.port + loc.pathname;
-    var transport = new Thrift.TWebSocketTransport(ws_uri);
-    var protocol  = new Thrift.Protocol(transport);
-    var client    = new ThriftTest.ThriftTestClient(protocol);
+    const transport = new Thrift.TWebSocketTransport(ws_uri);
+    const protocol  = new Thrift.Protocol(transport);
+    const client    = new ThriftTest.ThriftTestClient(protocol);
     transport.open();
   </script>
   <script type="text/javascript" src="test-async.js" charset="utf-8"></script>
 </head>
 <body>
-  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=test/ThriftTest.thrift;hb=HEAD">ThriftTest.thrift</a>)</h1>
+  <h1 id="qunit-header">Thrift Javascript Bindings: Unit Test (<a href="https://github.com/apache/thrift/blob/master/test/ThriftTest.thrift">ThriftTest.thrift</a>)</h1>
   <h2 id="qunit-banner"></h2>
   <div id="qunit-testrunner-toolbar"></div>
   <h2 id="qunit-userAgent"></h2>
diff --git a/lib/lua/Makefile.am b/lib/lua/Makefile.am
index 3dfc27c..5b0f17a 100644
--- a/lib/lua/Makefile.am
+++ b/lib/lua/Makefile.am
@@ -23,9 +23,9 @@
 
 lib_LTLIBRARIES = \
 			libluasocket.la \
+			liblualongnumber.la \
 			libluabpack.la \
-			libluabitwise.la \
-			liblualongnumber.la
+			libluabitwise.la
 
 libluasocket_la_SOURCES = \
 			src/luasocket.c \
diff --git a/lib/lua/TFramedTransport.lua b/lib/lua/TFramedTransport.lua
index 437b701..768e2d9 100644
--- a/lib/lua/TFramedTransport.lua
+++ b/lib/lua/TFramedTransport.lua
@@ -100,7 +100,7 @@
   local tmp = self.wBuf
   self.wBuf = ''
   local frame_len_buf = libluabpack.bpack("i", string.len(tmp))
-  self.trans:write(frame_len_buf)
+  tmp = frame_len_buf .. tmp
   self.trans:write(tmp)
   self.trans:flush()
 end
diff --git a/lib/lua/THttpTransport.lua b/lib/lua/THttpTransport.lua
index 041e421..2951db7 100644
--- a/lib/lua/THttpTransport.lua
+++ b/lib/lua/THttpTransport.lua
@@ -25,7 +25,7 @@
   wBuf = '',
   rBuf = '',
   CRLF = '\r\n',
-  VERSION = '0.11.0',
+  VERSION = version,
   isServer = true
 }
 
diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua
index a9a9078..68d4ba8 100644
--- a/lib/lua/Thrift.lua
+++ b/lib/lua/Thrift.lua
@@ -48,7 +48,7 @@
   return count
 end
 
-version = 1.0
+version = '1.0.0'
 
 TType = {
   STOP   = 0,
diff --git a/lib/netcore/Makefile.am b/lib/netcore/Makefile.am
index facee11..caf3f34 100644
--- a/lib/netcore/Makefile.am
+++ b/lib/netcore/Makefile.am
@@ -19,87 +19,23 @@
 
 SUBDIRS = . 
 
-THRIFT = $(top_builddir)/compiler/cpp/thrift
-
-TESTDIR = Tests/Thrift.PublicInterfaces.Compile.Tests
-GENDIR = $(TESTDIR)/gen-netcore
-
-THRIFTCODE = \
-			Thrift/Thrift.csproj \
-			Thrift/ITAsyncProcessor.cs \
-			Thrift/ITProcessorFactory.cs \
-			Thrift/SingletonTProcessorFactory.cs \
-			Thrift/TApplicationException.cs \
-			Thrift/TBaseClient.cs \
-			Thrift/TException.cs \
-			Thrift/TMultiplexedProcessor.cs \
-			Thrift/Collections/TCollections.cs \
-			Thrift/Collections/THashSet.cs \
-			Thrift/Properties/AssemblyInfo.cs \
-			Thrift/Protocols/ITProtocolFactory.cs \
-			Thrift/Protocols/TAbstractBase.cs \
-			Thrift/Protocols/TBase.cs \
-			Thrift/Protocols/TBinaryProtocol.cs \
-			Thrift/Protocols/TCompactProtocol.cs \
-			Thrift/Protocols/TJSONProtocol.cs \
-			Thrift/Protocols/TMultiplexedProtocol.cs \
-			Thrift/Protocols/TProtocol.cs \
-			Thrift/Protocols/TProtocolDecorator.cs \
-			Thrift/Protocols/TProtocolException.cs \
-			Thrift/Protocols/Entities/TField.cs \
-			Thrift/Protocols/Entities/TList.cs \
-			Thrift/Protocols/Entities/TMap.cs \
-			Thrift/Protocols/Entities/TMessage.cs \
-			Thrift/Protocols/Entities/TMessageType.cs \
-			Thrift/Protocols/Entities/TSet.cs \
-			Thrift/Protocols/Entities/TStruct.cs \
-			Thrift/Protocols/Entities/TType.cs \
-			Thrift/Protocols/Utilities/TBase64Utils.cs \
-			Thrift/Protocols/Utilities/TProtocolUtil.cs \
-			Thrift/Server/AsyncBaseServer.cs \
-			Thrift/Server/TBaseServer.cs \
-			Thrift/Server/TServerEventHandler.cs \
-			Thrift/Transports/TClientTransport.cs \
-			Thrift/Transports/TServerTransport.cs \
-			Thrift/Transports/TTransportException.cs \
-			Thrift/Transports/TTransportFactory.cs \
-			Thrift/Transports/Client/TBufferedClientTransport.cs \
-			Thrift/Transports/Client/TFramedClientTransport.cs \
-			Thrift/Transports/Client/THttpClientTransport.cs \
-			Thrift/Transports/Client/TMemoryBufferClientTransport.cs \
-			Thrift/Transports/Client/TNamedPipeClientTransport.cs \
-			Thrift/Transports/Client/TSocketClientTransport.cs \
-			Thrift/Transports/Client/TStreamClientTransport.cs \
-			Thrift/Transports/Client/TTlsSocketClientTransport.cs \
-			Thrift/Transports/Server/THttpServerTransport.cs \
-			Thrift/Transports/Server/TNamedPipeServerTransport.cs \
-			Thrift/Transports/Server/TServerFramedTransport.cs \
-			Thrift/Transports/Server/TServerSocketTransport.cs \
-			Thrift/Transports/Server/TTlsServerSocketTransport.cs 
-
-all-local: \
-	Thrift.dll
-
-Thrift.dll: $(THRIFTCODE)
-	$(MKDIR_P) $(GENDIR)
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(TESTDIR)/CassandraTest.thrift
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/test/ThriftTest.thrift
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/contrib/fb303/if/fb303.thrift
-	$(DOTNETCORE) --info
-	$(DOTNETCORE) restore
+all-local:
 	$(DOTNETCORE) build
 
+check-local:
+	$(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj
+	${DOTNETCORE} test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
+
 clean-local:
-	$(RM) Thrift.dll
-	$(RM) -r $(GENDIR)
 	$(RM) -r Thrift/bin
 	$(RM) -r Thrift/obj
-	$(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin
-	$(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj
 
 EXTRA_DIST = \
-			 $(THRIFTCODE) \
-			 Thrift.sln \
-			 Tests \
-			 README.md
-			 
+	README.md \
+	Tests \
+	Thrift \
+	Thrift.sln \
+	build.cmd \
+	build.sh \
+	runtests.cmd \
+	runtests.sh
diff --git a/lib/netcore/README.md b/lib/netcore/README.md
index 39492f3..94b047f 100644
--- a/lib/netcore/README.md
+++ b/lib/netcore/README.md
@@ -10,7 +10,10 @@
 - .NET Standard 1.6 (SDK 2.0.0)
 
 # How to build on Windows
+- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable
 - Open the Thrift.sln project with Visual Studio and build.
+or 
+- Build with scripts
 
 # How to build on Unix
 - Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore b/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore
new file mode 100644
index 0000000..7254c31
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/Apache
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
new file mode 100644
index 0000000..bc4afa1
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
@@ -0,0 +1,502 @@
+// 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.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using KellermanSoftware.CompareNetObjects;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Transports.Client;
+
+namespace Thrift.IntegrationTests.Protocols
+{
+    [TestClass]
+    public class ProtocolsOperationsTests
+    {
+        private readonly CompareLogic _compareLogic = new CompareLogic();
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Call)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Reply)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Call)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Reply)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Call)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Reply)]
+        public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageType)
+        {
+            var expected = new TMessage(nameof(TMessage), messageType, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteMessageBeginAsync(expected);
+                    await protocol.WriteMessageEndAsync();
+
+                    stream.Seek(0, SeekOrigin.Begin);
+
+                    var actualMessage = await protocol.ReadMessageBeginAsync();
+                    await protocol.ReadMessageEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actualMessage);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        [ExpectedException(typeof(Exception))]
+        public async Task WriteReadStruct_Test(Type protocolType)
+        {
+            var expected = new TStruct(nameof(TStruct));
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteStructBeginAsync(expected);
+                    await protocol.WriteStructEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadStructBeginAsync();
+                    await protocol.ReadStructEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        [ExpectedException(typeof(Exception))]
+        public async Task WriteReadField_Test(Type protocolType)
+        {
+            var expected = new TField(nameof(TField), TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteFieldBeginAsync(expected);
+                    await protocol.WriteFieldEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadFieldBeginAsync();
+                    await protocol.ReadFieldEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadMap_Test(Type protocolType)
+        {
+            var expected = new TMap(TType.String, TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteMapBeginAsync(expected);
+                    await protocol.WriteMapEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadMapBeginAsync();
+                    await protocol.ReadMapEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadList_Test(Type protocolType)
+        {
+            var expected = new TList(TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteListBeginAsync(expected);
+                    await protocol.WriteListEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadListBeginAsync();
+                    await protocol.ReadListEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadSet_Test(Type protocolType)
+        {
+            var expected = new TSet(TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteSetBeginAsync(expected);
+                    await protocol.WriteSetEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadSetBeginAsync();
+                    await protocol.ReadSetEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadBool_Test(Type protocolType)
+        {
+            var expected = true;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteBoolAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadBoolAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadByte_Test(Type protocolType)
+        {
+            var expected = sbyte.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteByteAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadByteAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI16_Test(Type protocolType)
+        {
+            var expected = short.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI16Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI16Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI32_Test(Type protocolType)
+        {
+            var expected = int.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI32Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI32Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI64_Test(Type protocolType)
+        {
+            var expected = long.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI64Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI64Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadDouble_Test(Type protocolType)
+        {
+            var expected = double.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteDoubleAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadDoubleAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadString_Test(Type protocolType)
+        {
+            var expected = nameof(String);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteStringAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadStringAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadBinary_Test(Type protocolType)
+        {
+            var expected = Encoding.UTF8.GetBytes(nameof(String));
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteBinaryAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadBinaryAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        private static Tuple<Stream, TProtocol> GetProtocolInstance(Type protocolType)
+        {
+            var memoryStream = new MemoryStream();
+            var streamClientTransport = new TStreamClientTransport(memoryStream, memoryStream);
+            var protocol = (TProtocol) Activator.CreateInstance(protocolType, streamClientTransport);
+            return new Tuple<Stream, TProtocol>(memoryStream, protocol);
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
new file mode 100644
index 0000000..f25dac5
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Thrift.IntegrationTests</AssemblyName>
+    <PackageId>Thrift.IntegrationTests</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="CompareNETObjects" Version="4.3.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
+    <PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
+    <PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="4.4.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore
new file mode 100644
index 0000000..ae929a3
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore
@@ -0,0 +1,4 @@
+# ignore for autogenerated files
+/ThriftTest
+/Apache
+/Facebook
diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
index f551116..c4a84a3 100644
--- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
+++ b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
@@ -18,4 +18,19 @@
     <PackageReference Include="System.ServiceModel.Primitives" Version="[4.1.0,)" />
   </ItemGroup>
 
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+  </Target>
+
 </Project>
diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
new file mode 100644
index 0000000..1be99b4
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
@@ -0,0 +1,83 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Collections;
+
+namespace Thrift.Tests.Collections
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class TCollectionsTests
+    {
+        //TODO: Add tests for IEnumerable with objects and primitive values inside
+
+        [TestMethod]
+        public void TCollection_Equals_Primitive_Test()
+        {
+            var collection1 = new List<int> {1,2,3};
+            var collection2 = new List<int> {1,2,3};
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            Assert.IsTrue(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_Primitive_Different_Test()
+        {
+            var collection1 = new List<int> { 1, 2, 3 };
+            var collection2 = new List<int> { 1, 2 };
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            Assert.IsFalse(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_Objects_Test()
+        {
+            var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+            var collection2 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            // references to different collections
+            Assert.IsFalse(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_OneAndTheSameObject_Test()
+        {
+            var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+            var collection2 = collection1;
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            // references to one and the same collection
+            Assert.IsTrue(result);
+        }
+
+        private class ExampleClass
+        {
+            public int X { get; set; }
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs
new file mode 100644
index 0000000..8de573e
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs
@@ -0,0 +1,71 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Collections;
+
+namespace Thrift.Tests.Collections
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class THashSetTests
+    {
+        [TestMethod]
+        public void THashSet_Equals_Primitive_Test()
+        {
+            const int value = 1;
+
+            var hashSet = new THashSet<int> {value};
+            
+            Assert.IsTrue(hashSet.Contains(value));
+
+            hashSet.Remove(value);
+
+            Assert.IsTrue(hashSet.Count == 0);
+
+            hashSet.Add(value);
+
+            Assert.IsTrue(hashSet.Contains(value));
+
+            hashSet.Clear();
+
+            Assert.IsTrue(hashSet.Count == 0);
+
+            var newArr = new int[1];
+            hashSet.Add(value);
+            hashSet.CopyTo(newArr, 0);
+
+            Assert.IsTrue(newArr.Contains(value));
+
+            var en = hashSet.GetEnumerator();
+            en.MoveNext();
+
+            Assert.IsTrue((int)en.Current == value);
+            
+            using (var ien = ((IEnumerable<int>)hashSet).GetEnumerator())
+            {
+                ien.MoveNext();
+
+                Assert.IsTrue(ien.Current == value);
+            }
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs
new file mode 100644
index 0000000..cdc8317
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs
@@ -0,0 +1,172 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Protocols.Utilities;
+
+namespace Thrift.Tests.Protocols
+{
+    [TestClass]
+    public class TJSONProtocolHelperTests
+    {
+        [TestMethod]
+        public void GetTypeNameForTypeId_Test()
+        {
+            // input/output
+            var sets = new List<Tuple<TType, byte[]>>
+            {
+                new Tuple<TType, byte[]>(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool),
+                new Tuple<TType, byte[]>(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte),
+                new Tuple<TType, byte[]>(TType.I16, TJSONProtocolConstants.TypeNames.NameI16),
+                new Tuple<TType, byte[]>(TType.I32, TJSONProtocolConstants.TypeNames.NameI32),
+                new Tuple<TType, byte[]>(TType.I64, TJSONProtocolConstants.TypeNames.NameI64),
+                new Tuple<TType, byte[]>(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble),
+                new Tuple<TType, byte[]>(TType.String, TJSONProtocolConstants.TypeNames.NameString),
+                new Tuple<TType, byte[]>(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct),
+                new Tuple<TType, byte[]>(TType.Map, TJSONProtocolConstants.TypeNames.NameMap),
+                new Tuple<TType, byte[]>(TType.Set, TJSONProtocolConstants.TypeNames.NameSet),
+                new Tuple<TType, byte[]>(TType.List, TJSONProtocolConstants.TypeNames.NameList),
+            };
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.GetTypeNameForTypeId(t.Item1) == t.Item2, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeNameForTypeId_TStop_Test()
+        {
+            TJSONProtocolHelper.GetTypeNameForTypeId(TType.Stop);
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeNameForTypeId_NonExistingTType_Test()
+        {
+            TJSONProtocolHelper.GetTypeNameForTypeId((TType)100);
+        }
+
+        [TestMethod]
+        public void GetTypeIdForTypeName_Test()
+        {
+            // input/output
+            var sets = new List<Tuple<TType, byte[]>>
+            {
+                new Tuple<TType, byte[]>(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool),
+                new Tuple<TType, byte[]>(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte),
+                new Tuple<TType, byte[]>(TType.I16, TJSONProtocolConstants.TypeNames.NameI16),
+                new Tuple<TType, byte[]>(TType.I32, TJSONProtocolConstants.TypeNames.NameI32),
+                new Tuple<TType, byte[]>(TType.I64, TJSONProtocolConstants.TypeNames.NameI64),
+                new Tuple<TType, byte[]>(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble),
+                new Tuple<TType, byte[]>(TType.String, TJSONProtocolConstants.TypeNames.NameString),
+                new Tuple<TType, byte[]>(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct),
+                new Tuple<TType, byte[]>(TType.Map, TJSONProtocolConstants.TypeNames.NameMap),
+                new Tuple<TType, byte[]>(TType.Set, TJSONProtocolConstants.TypeNames.NameSet),
+                new Tuple<TType, byte[]>(TType.List, TJSONProtocolConstants.TypeNames.NameList),
+            };
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.GetTypeIdForTypeName(t.Item2) == t.Item1, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_TStopTypeName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new []{(byte)TType.Stop, (byte)TType.Stop});
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_NonExistingTypeName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new byte[]{100});
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_EmptyName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new byte[] {});
+        }
+
+        [TestMethod]
+        public void IsJsonNumeric_Test()
+        {
+            // input/output
+            var correctJsonNumeric = "+-.0123456789Ee";
+            var incorrectJsonNumeric = "AaBcDd/*\\";
+
+            var sets = correctJsonNumeric.Select(ch => new Tuple<byte, bool>((byte) ch, true)).ToList();
+            sets.AddRange(incorrectJsonNumeric.Select(ch => new Tuple<byte, bool>((byte) ch, false)));
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.IsJsonNumeric(t.Item1) == t.Item2, $"Wrong mapping of Char {t.Item1} to bool: {t.Item2}");
+            }
+        }
+
+        [TestMethod]
+        public void ToHexVal_Test()
+        {
+            // input/output
+            var chars = "0123456789abcdef";
+            var expectedHexValues = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+            var sets = chars.Select((ch, i) => new Tuple<char, byte>(ch, expectedHexValues[i])).ToList();
+
+            foreach (var t in sets)
+            {
+                var actualResult = TJSONProtocolHelper.ToHexVal((byte)t.Item1);
+                Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of char byte {t.Item1} to it expected hex value: {t.Item2}. Actual hex value: {actualResult}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void ToHexVal_WrongInputChar_Test()
+        {
+            TJSONProtocolHelper.ToHexVal((byte)'s');
+        }
+
+        [TestMethod]
+        public void ToHexChar_Test()
+        {
+            // input/output
+            var hexValues = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+            var expectedChars = "0123456789abcdef";
+            
+
+            var sets = hexValues.Select((hv, i) => new Tuple<byte, char>(hv, expectedChars[i])).ToList();
+
+            foreach (var t in sets)
+            {
+                var actualResult = TJSONProtocolHelper.ToHexChar(t.Item1);
+                Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of hex value {t.Item1} to it expected char: {t.Item2}. Actual hex value: {actualResult}");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs
new file mode 100644
index 0000000..5237360
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs
@@ -0,0 +1,67 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NSubstitute;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Transports;
+using Thrift.Transports.Client;
+
+namespace Thrift.Tests.Protocols
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class TJSONProtocolTests
+    {
+        [TestMethod]
+        public void TJSONProtocol_Can_Create_Instance_Test()
+        {
+            var httpClientTransport = Substitute.For<THttpClientTransport>(new Uri("http://localhost"), null);
+
+            var result = new TJSONProtocolWrapper(httpClientTransport);
+
+            Assert.IsNotNull(result);
+            Assert.IsNotNull(result.WrappedContext);
+            Assert.IsNotNull(result.WrappedReader);
+            Assert.IsNotNull(result.Transport);
+            Assert.IsTrue(result.WrappedRecursionDepth == 0);
+            Assert.IsTrue(result.WrappedRecursionLimit == TProtocol.DefaultRecursionDepth);
+
+            Assert.IsTrue(result.Transport.Equals(httpClientTransport));
+            Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase));
+            Assert.IsTrue(result.WrappedReader.GetType().Name.Equals("LookaheadReader", StringComparison.OrdinalIgnoreCase));
+        }
+
+        private class TJSONProtocolWrapper : TJsonProtocol
+        {
+            public TJSONProtocolWrapper(TClientTransport trans) : base(trans)
+            {
+            }
+
+            public object WrappedContext => Context;
+            public object WrappedReader => Reader;
+            public int WrappedRecursionDepth => RecursionDepth;
+            public int WrappedRecursionLimit => RecursionLimit;
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj
new file mode 100644
index 0000000..e46f165
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="CompareNETObjects" Version="4.3.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
+    <PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
+    <PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
+    <PackageReference Include="NSubstitute" Version="3.1.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/lib/netcore/Thrift.sln b/lib/netcore/Thrift.sln
index a730269..fe30aa5 100644
--- a/lib/netcore/Thrift.sln
+++ b/lib/netcore/Thrift.sln
@@ -4,10 +4,14 @@
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{0676962B-98C2-49EC-B4C4-7A0451D0640B}"
-EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "Thrift\Thrift.csproj", "{D85F572F-7D80-40A4-9A9B-2731ED187C24}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{9F9A11BF-3C95-4E80-AFBF-768541996844}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrift.Tests\Thrift.Tests.csproj", "{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A429F05B-F511-45EF-AE7B-04E1AE9C9367}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -18,18 +22,6 @@
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x64.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x86.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x64.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x64.Build.0 = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x86.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x86.Build.0 = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -42,12 +34,50 @@
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x64.Build.0 = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.ActiveCfg = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{9F9A11BF-3C95-4E80-AFBF-768541996844} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9}
diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs
index 61cd3e3..8341723 100644
--- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs
+++ b/lib/netcore/Thrift/Properties/AssemblyInfo.cs
@@ -52,5 +52,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 
-[assembly: AssemblyVersion("0.11.0.1")]
-[assembly: AssemblyFileVersion("0.11.0.1")]
\ No newline at end of file
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/netcore/Thrift/Protocols/TAbstractBase.cs b/lib/netcore/Thrift/Protocols/TAbstractBase.cs
index eddb85e..4e18681 100644
--- a/lib/netcore/Thrift/Protocols/TAbstractBase.cs
+++ b/lib/netcore/Thrift/Protocols/TAbstractBase.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Protocols/TBase.cs b/lib/netcore/Thrift/Protocols/TBase.cs
index cd11099..014e1ae 100644
--- a/lib/netcore/Thrift/Protocols/TBase.cs
+++ b/lib/netcore/Thrift/Protocols/TBase.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs b/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
index fa0c5fc..deec85c 100644
--- a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -79,7 +79,7 @@
             }
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -293,15 +293,15 @@
             await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 return;
             }
 
-            await WriteI32Async(b.Length, cancellationToken);
-            await Trans.WriteAsync(b, 0, b.Length, cancellationToken);
+            await WriteI32Async(bytes.Length, cancellationToken);
+            await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
         public override async Task<TMessage> ReadMessageBeginAsync(CancellationToken cancellationToken)
@@ -511,8 +511,13 @@
 
             var i32In = new byte[4];
             await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken);
-            var result = ((i32In[0] & 0xff) << 24) | ((i32In[1] & 0xff) << 16) | ((i32In[2] & 0xff) << 8) |
-                         i32In[3] & 0xff;
+
+            var result = 
+                ((i32In[0] & 0xff) << 24) | 
+                ((i32In[1] & 0xff) << 16) | 
+                ((i32In[2] & 0xff) << 8) |
+                i32In[3] & 0xff;
+
             return result;
         }
 
diff --git a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs b/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
index 6d5e0bf..cecdf03 100644
--- a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -114,7 +114,7 @@
         ///     use it as an opportunity to put special placeholder markers on the field
         ///     stack so we can get the field id deltas correct.
         /// </summary>
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -383,16 +383,16 @@
             await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 return;
             }
 
-            var bufferTuple = CreateWriteVarInt32((uint) b.Length);
+            var bufferTuple = CreateWriteVarInt32((uint) bytes.Length);
             await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken);
-            await Trans.WriteAsync(b, 0, b.Length, cancellationToken);
+            await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
         public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken)
diff --git a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs b/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
index a4ddd5b..6d33f02 100644
--- a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
@@ -19,6 +19,7 @@
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
+using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -28,8 +29,6 @@
 
 namespace Thrift.Protocols
 {
-    //TODO: implementation of TProtocol
-
     /// <summary>
     ///     JSON protocol implementation for thrift.
     ///     This is a full-featured protocol supporting Write and Read.
@@ -42,53 +41,14 @@
     {
         private const long Version = 1;
 
-        private const int DefStringSize = 16;
-
-        private static readonly byte[] Comma = {(byte) ','};
-        private static readonly byte[] Colon = {(byte) ':'};
-        private static readonly byte[] Lbrace = {(byte) '{'};
-        private static readonly byte[] Rbrace = {(byte) '}'};
-        private static readonly byte[] Lbracket = {(byte) '['};
-        private static readonly byte[] Rbracket = {(byte) ']'};
-        private static readonly byte[] Quote = {(byte) '"'};
-        private static readonly byte[] Backslash = {(byte) '\\'};
-
-        private static readonly byte[] NameBool = {(byte) 't', (byte) 'f'};
-        private static readonly byte[] NameByte = {(byte) 'i', (byte) '8'};
-        private static readonly byte[] NameI16 = {(byte) 'i', (byte) '1', (byte) '6'};
-        private static readonly byte[] NameI32 = {(byte) 'i', (byte) '3', (byte) '2'};
-        private static readonly byte[] NameI64 = {(byte) 'i', (byte) '6', (byte) '4'};
-        private static readonly byte[] NameDouble = {(byte) 'd', (byte) 'b', (byte) 'l'};
-        private static readonly byte[] NameStruct = {(byte) 'r', (byte) 'e', (byte) 'c'};
-        private static readonly byte[] NameString = {(byte) 's', (byte) 't', (byte) 'r'};
-        private static readonly byte[] NameMap = {(byte) 'm', (byte) 'a', (byte) 'p'};
-        private static readonly byte[] NameList = {(byte) 'l', (byte) 's', (byte) 't'};
-        private static readonly byte[] NameSet = {(byte) 's', (byte) 'e', (byte) 't'};
-
-        private readonly char[] _escapeChars = "\"\\/bfnrt".ToCharArray();
-
-        private readonly byte[] _escapeCharVals =
-        {
-            (byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'
-        };
-
-        private readonly byte[] _escseq = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'};
-
-        private readonly byte[] _jsonCharTable =
-        {
-            0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-        };
-
         // Temporary buffer used by several methods
         private readonly byte[] _tempBuffer = new byte[4];
 
         // Current context that we are in
-        protected JsonBaseContext Context;
+        protected JSONBaseContext Context;
 
         // Stack of nested contexts that we may be in
-        protected Stack<JsonBaseContext> ContextStack = new Stack<JsonBaseContext>();
+        protected Stack<JSONBaseContext> ContextStack = new Stack<JSONBaseContext>();
 
         // Reader that manages a 1-byte buffer
         protected LookaheadReader Reader;
@@ -102,105 +62,14 @@
         public TJsonProtocol(TClientTransport trans)
             : base(trans)
         {
-            //throw new NotImplementedException("TJsonProtocol is not fully ready for usage");
-
-            Context = new JsonBaseContext(this);
+            Context = new JSONBaseContext(this);
             Reader = new LookaheadReader(this);
         }
 
-        private static byte[] GetTypeNameForTypeId(TType typeId)
-        {
-            switch (typeId)
-            {
-                case TType.Bool:
-                    return NameBool;
-                case TType.Byte:
-                    return NameByte;
-                case TType.I16:
-                    return NameI16;
-                case TType.I32:
-                    return NameI32;
-                case TType.I64:
-                    return NameI64;
-                case TType.Double:
-                    return NameDouble;
-                case TType.String:
-                    return NameString;
-                case TType.Struct:
-                    return NameStruct;
-                case TType.Map:
-                    return NameMap;
-                case TType.Set:
-                    return NameSet;
-                case TType.List:
-                    return NameList;
-                default:
-                    throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
-            }
-        }
-
-        private static TType GetTypeIdForTypeName(byte[] name)
-        {
-            var result = TType.Stop;
-            if (name.Length > 1)
-            {
-                switch (name[0])
-                {
-                    case (byte) 'd':
-                        result = TType.Double;
-                        break;
-                    case (byte) 'i':
-                        switch (name[1])
-                        {
-                            case (byte) '8':
-                                result = TType.Byte;
-                                break;
-                            case (byte) '1':
-                                result = TType.I16;
-                                break;
-                            case (byte) '3':
-                                result = TType.I32;
-                                break;
-                            case (byte) '6':
-                                result = TType.I64;
-                                break;
-                        }
-                        break;
-                    case (byte) 'l':
-                        result = TType.List;
-                        break;
-                    case (byte) 'm':
-                        result = TType.Map;
-                        break;
-                    case (byte) 'r':
-                        result = TType.Struct;
-                        break;
-                    case (byte) 's':
-                        if (name[1] == (byte) 't')
-                        {
-                            result = TType.String;
-                        }
-                        else if (name[1] == (byte) 'e')
-                        {
-                            result = TType.Set;
-                        }
-                        break;
-                    case (byte) 't':
-                        result = TType.Bool;
-                        break;
-                }
-            }
-            if (result == TType.Stop)
-            {
-                throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
-            }
-            return result;
-        }
-
         /// <summary>
         ///     Push a new JSON context onto the stack.
         /// </summary>
-        protected void PushContext(JsonBaseContext c)
+        protected void PushContext(JSONBaseContext c)
         {
             ContextStack.Push(Context);
             Context = c;
@@ -219,94 +88,60 @@
         ///     Marked protected to avoid synthetic accessor in JSONListContext.Read
         ///     and JSONPairContext.Read
         /// </summary>
-        protected async Task ReadJsonSyntaxCharAsync(byte[] b, CancellationToken cancellationToken)
+        protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             var ch = await Reader.ReadAsync(cancellationToken);
-            if (ch != b[0])
+            if (ch != bytes[0])
             {
                 throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}");
             }
         }
 
         /// <summary>
-        ///     Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
-        ///     corresponding hex value
-        /// </summary>
-        private static byte HexVal(byte ch)
-        {
-            if ((ch >= '0') && (ch <= '9'))
-            {
-                return (byte) ((char) ch - '0');
-            }
-
-            if ((ch >= 'a') && (ch <= 'f'))
-            {
-                ch += 10;
-                return (byte) ((char) ch - 'a');
-            }
-
-            throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character");
-        }
-
-        /// <summary>
-        ///     Convert a byte containing a hex value to its corresponding hex character
-        /// </summary>
-        private static byte HexChar(byte val)
-        {
-            val &= 0x0F;
-            if (val < 10)
-            {
-                return (byte) ((char) val + '0');
-            }
-            val -= 10;
-            return (byte) ((char) val + 'a');
-        }
-
-        /// <summary>
         ///     Write the bytes in array buf as a JSON characters, escaping as needed
         /// </summary>
-        private async Task WriteJsonStringAsync(byte[] b, CancellationToken cancellationToken)
+        private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
-            var len = b.Length;
+            var len = bytes.Length;
             for (var i = 0; i < len; i++)
             {
-                if ((b[i] & 0x00FF) >= 0x30)
+                if ((bytes[i] & 0x00FF) >= 0x30)
                 {
-                    if (b[i] == Backslash[0])
+                    if (bytes[i] == TJSONProtocolConstants.Backslash[0])
                     {
-                        await Trans.WriteAsync(Backslash, cancellationToken);
-                        await Trans.WriteAsync(Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
                     }
                     else
                     {
-                        await Trans.WriteAsync(b, i, 1, cancellationToken);
+                        await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken);
                     }
                 }
                 else
                 {
-                    _tempBuffer[0] = _jsonCharTable[b[i]];
+                    _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]];
                     if (_tempBuffer[0] == 1)
                     {
-                        await Trans.WriteAsync(b, i, 1, cancellationToken);
+                        await Trans.WriteAsync(bytes, i, 1, cancellationToken);
                     }
                     else if (_tempBuffer[0] > 1)
                     {
-                        await Trans.WriteAsync(Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
                         await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken);
                     }
                     else
                     {
-                        await Trans.WriteAsync(_escseq, cancellationToken);
-                        _tempBuffer[0] = HexChar((byte) (b[i] >> 4));
-                        _tempBuffer[1] = HexChar(b[i]);
+                        await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken);
+                        _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4));
+                        _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]);
                         await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken);
                     }
                 }
             }
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
         }
 
         /// <summary>
@@ -321,14 +156,15 @@
             var escapeNum = Context.EscapeNumbers();
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
-            await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken);
+            var bytes = Utf8Encoding.GetBytes(str);
+            await Trans.WriteAsync(bytes, cancellationToken);
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
         }
 
@@ -361,14 +197,14 @@
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken);
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
         }
 
@@ -376,26 +212,18 @@
         ///     Write out contents of byte array b as a JSON string with base-64 encoded
         ///     data
         /// </summary>
-        private async Task WriteJsonBase64Async(byte[] b, CancellationToken cancellationToken)
+        private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
-            var len = b.Length;
+            var len = bytes.Length;
             var off = 0;
 
-            // Ignore padding
-            var bound = len >= 2 ? len - 2 : 0;
-
-            for (var i = len - 1; i >= bound && b[i] == '='; --i)
-            {
-                --len;
-            }
-
             while (len >= 3)
             {
                 // Encode 3 bytes at a time
-                TBase64Utils.Encode(b, off, 3, _tempBuffer, 0);
+                TBase64Helper.Encode(bytes, off, 3, _tempBuffer, 0);
                 await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken);
                 off += 3;
                 len -= 3;
@@ -404,37 +232,37 @@
             if (len > 0)
             {
                 // Encode remainder
-                TBase64Utils.Encode(b, off, len, _tempBuffer, 0);
+                TBase64Helper.Encode(bytes, off, len, _tempBuffer, 0);
                 await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken);
             }
 
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
         }
 
         private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Lbrace, cancellationToken);
-            PushContext(new JsonPairContext(this));
+            await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken);
+            PushContext(new JSONPairContext(this));
         }
 
         private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken)
         {
             PopContext();
-            await Trans.WriteAsync(Rbrace, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken);
         }
 
         private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Lbracket, cancellationToken);
-            PushContext(new JsonListContext(this));
+            await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken);
+            PushContext(new JSONListContext(this));
         }
 
         private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken)
         {
             PopContext();
-            await Trans.WriteAsync(Rbracket, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken);
         }
 
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
@@ -454,7 +282,7 @@
             await WriteJsonArrayEndAsync(cancellationToken);
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             await WriteJsonObjectStartAsync(cancellationToken);
         }
@@ -468,7 +296,7 @@
         {
             await WriteJsonIntegerAsync(field.ID, cancellationToken);
             await WriteJsonObjectStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(field.Type), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken);
         }
 
         public override async Task WriteFieldEndAsync(CancellationToken cancellationToken)
@@ -487,8 +315,8 @@
         public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(map.KeyType), cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(map.ValueType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken);
             await WriteJsonIntegerAsync(map.Count, cancellationToken);
             await WriteJsonObjectStartAsync(cancellationToken);
         }
@@ -502,7 +330,7 @@
         public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(list.ElementType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken);
             await WriteJsonIntegerAsync(list.Count, cancellationToken);
         }
 
@@ -514,7 +342,7 @@
         public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(set.ElementType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken);
             await WriteJsonIntegerAsync(set.Count, cancellationToken);
         }
 
@@ -559,9 +387,9 @@
             await WriteJsonStringAsync(b, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
-            await WriteJsonBase64Async(b, cancellationToken);
+            await WriteJsonBase64Async(bytes, cancellationToken);
         }
 
         /// <summary>
@@ -580,18 +408,18 @@
                     await Context.ReadAsync(cancellationToken);
                 }
 
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
                 while (true)
                 {
                     var ch = await Reader.ReadAsync(cancellationToken);
-                    if (ch == Quote[0])
+                    if (ch == TJSONProtocolConstants.Quote[0])
                     {
                         break;
                     }
 
                     // escaped?
-                    if (ch != _escseq[0])
+                    if (ch != TJSONProtocolConstants.EscSequences[0])
                     {
                         await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken);
                         continue;
@@ -599,26 +427,25 @@
 
                     // distinguish between \uXXXX and \?
                     ch = await Reader.ReadAsync(cancellationToken);
-                    if (ch != _escseq[1]) // control chars like \n
+                    if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n
                     {
-                        var off = Array.IndexOf(_escapeChars, (char) ch);
+                        var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch);
                         if (off == -1)
                         {
                             throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char");
                         }
-                        ch = _escapeCharVals[off];
+                        ch = TJSONProtocolConstants.EscapeCharValues[off];
                         await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken);
                         continue;
                     }
 
-
                     // it's \uXXXX
                     await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken);
 
-                    var wch = (short) ((HexVal(_tempBuffer[0]) << 12) +
-                                       (HexVal(_tempBuffer[1]) << 8) +
-                                       (HexVal(_tempBuffer[2]) << 4) +
-                                       HexVal(_tempBuffer[3]));
+                    var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) +
+                                       (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) +
+                                       (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) +
+                                       TJSONProtocolHelper.ToHexVal(_tempBuffer[3]));
 
                     if (char.IsHighSurrogate((char) wch))
                     {
@@ -657,34 +484,6 @@
         }
 
         /// <summary>
-        ///     Return true if the given byte could be a valid part of a JSON number.
-        /// </summary>
-        private static bool IsJsonNumeric(byte b)
-        {
-            switch (b)
-            {
-                case (byte) '+':
-                case (byte) '-':
-                case (byte) '.':
-                case (byte) '0':
-                case (byte) '1':
-                case (byte) '2':
-                case (byte) '3':
-                case (byte) '4':
-                case (byte) '5':
-                case (byte) '6':
-                case (byte) '7':
-                case (byte) '8':
-                case (byte) '9':
-                case (byte) 'E':
-                case (byte) 'e':
-                    return true;
-            }
-
-            return false;
-        }
-
-        /// <summary>
         ///     Read in a sequence of characters that are all valid in JSON numbers. Does
         ///     not do a complete regex check to validate that this is actually a number.
         /// </summary>
@@ -693,12 +492,21 @@
             var strbld = new StringBuilder();
             while (true)
             {
-                var ch = await Reader.PeekAsync(cancellationToken);
-                if (!IsJsonNumeric(ch))
+                //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions
+                try
+                {
+                    var ch = await Reader.PeekAsync(cancellationToken);
+                    if (!TJSONProtocolHelper.IsJsonNumeric(ch))
+                    {
+                        break;
+                    }
+                    var c = (char)await Reader.ReadAsync(cancellationToken);
+                    strbld.Append(c);
+                }
+                catch (TTransportException)
                 {
                     break;
                 }
-                strbld.Append((char) await Reader.ReadAsync(cancellationToken));
             }
             return strbld.ToString();
         }
@@ -711,13 +519,13 @@
             await Context.ReadAsync(cancellationToken);
             if (Context.EscapeNumbers())
             {
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             var str = await ReadJsonNumericCharsAsync(cancellationToken);
             if (Context.EscapeNumbers())
             {
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             try
@@ -737,7 +545,7 @@
         private async Task<double> ReadJsonDoubleAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            if (await Reader.PeekAsync(cancellationToken) == Quote[0])
+            if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0])
             {
                 var arr = await ReadJsonStringAsync(true, cancellationToken);
                 var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
@@ -754,7 +562,7 @@
             if (Context.EscapeNumbers())
             {
                 // This will throw - we should have had a quote if escapeNum == true
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             try
@@ -787,7 +595,7 @@
             while (len > 4)
             {
                 // Decode 4 bytes at a time
-                TBase64Utils.Decode(b, off, 4, b, size); // NB: decoded in place
+                TBase64Helper.Decode(b, off, 4, b, size); // NB: decoded in place
                 off += 4;
                 len -= 4;
                 size += 3;
@@ -798,7 +606,7 @@
             if (len > 1)
             {
                 // Decode remainder
-                TBase64Utils.Decode(b, off, len, b, size); // NB: decoded in place
+                TBase64Helper.Decode(b, off, len, b, size); // NB: decoded in place
                 size += len - 1;
             }
 
@@ -811,26 +619,26 @@
         private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            await ReadJsonSyntaxCharAsync(Lbrace, cancellationToken);
-            PushContext(new JsonPairContext(this));
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken);
+            PushContext(new JSONPairContext(this));
         }
 
         private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken)
         {
-            await ReadJsonSyntaxCharAsync(Rbrace, cancellationToken);
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken);
             PopContext();
         }
 
         private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            await ReadJsonSyntaxCharAsync(Lbracket, cancellationToken);
-            PushContext(new JsonListContext(this));
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken);
+            PushContext(new JSONListContext(this));
         }
 
         private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken)
         {
-            await ReadJsonSyntaxCharAsync(Rbracket, cancellationToken);
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken);
             PopContext();
         }
 
@@ -870,7 +678,7 @@
         {
             var field = new TField();
             var ch = await Reader.PeekAsync(cancellationToken);
-            if (ch == Rbrace[0])
+            if (ch == TJSONProtocolConstants.RightBrace[0])
             {
                 field.Type = TType.Stop;
             }
@@ -878,7 +686,7 @@
             {
                 field.ID = (short) await ReadJsonIntegerAsync(cancellationToken);
                 await ReadJsonObjectStartAsync(cancellationToken);
-                field.Type = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+                field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             }
             return field;
         }
@@ -892,8 +700,8 @@
         {
             var map = new TMap();
             await ReadJsonArrayStartAsync(cancellationToken);
-            map.KeyType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
-            map.ValueType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             map.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             await ReadJsonObjectStartAsync(cancellationToken);
             return map;
@@ -909,7 +717,7 @@
         {
             var list = new TList();
             await ReadJsonArrayStartAsync(cancellationToken);
-            list.ElementType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             list.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             return list;
         }
@@ -923,7 +731,7 @@
         {
             var set = new TSet();
             await ReadJsonArrayStartAsync(cancellationToken);
-            set.ElementType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             set.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             return set;
         }
@@ -990,11 +798,11 @@
         ///     inserting/Reading additional JSON syntax characters
         ///     This base context does nothing.
         /// </summary>
-        protected class JsonBaseContext
+        protected class JSONBaseContext
         {
             protected TJsonProtocol Proto;
 
-            public JsonBaseContext(TJsonProtocol proto)
+            public JSONBaseContext(TJsonProtocol proto)
             {
                 Proto = proto;
             }
@@ -1025,11 +833,11 @@
         ///     Context for JSON lists. Will insert/Read commas before each item except
         ///     for the first one
         /// </summary>
-        protected class JsonListContext : JsonBaseContext
+        protected class JSONListContext : JSONBaseContext
         {
             private bool _first = true;
 
-            public JsonListContext(TJsonProtocol protocol)
+            public JSONListContext(TJsonProtocol protocol)
                 : base(protocol)
             {
             }
@@ -1042,7 +850,7 @@
                 }
                 else
                 {
-                    await Proto.Trans.WriteAsync(Comma, cancellationToken);
+                    await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken);
                 }
             }
 
@@ -1054,7 +862,7 @@
                 }
                 else
                 {
-                    await Proto.ReadJsonSyntaxCharAsync(Comma, cancellationToken);
+                    await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken);
                 }
             }
         }
@@ -1065,13 +873,14 @@
         ///     addition, will indicate that numbers in the key position need to be
         ///     escaped in quotes (since JSON keys must be strings).
         /// </summary>
-        protected class JsonPairContext : JsonBaseContext
+        // ReSharper disable once InconsistentNaming
+        protected class JSONPairContext : JSONBaseContext
         {
             private bool _colon = true;
 
             private bool _first = true;
 
-            public JsonPairContext(TJsonProtocol proto)
+            public JSONPairContext(TJsonProtocol proto)
                 : base(proto)
             {
             }
@@ -1085,7 +894,7 @@
                 }
                 else
                 {
-                    await Proto.Trans.WriteAsync(_colon ? Colon : Comma, cancellationToken);
+                    await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken);
                     _colon = !_colon;
                 }
             }
@@ -1099,7 +908,7 @@
                 }
                 else
                 {
-                    await Proto.ReadJsonSyntaxCharAsync(_colon ? Colon : Comma, cancellationToken);
+                    await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken);
                     _colon = !_colon;
                 }
             }
@@ -1142,6 +951,7 @@
                 }
                 else
                 {
+                    // find more easy way to avoid exception on reading primitive types
                     await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken);
                 }
                 return _data[0];
@@ -1160,6 +970,7 @@
 
                 if (!_hasData)
                 {
+                    // find more easy way to avoid exception on reading primitive types
                     await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken);
                 }
                 _hasData = true;
@@ -1167,4 +978,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs b/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
index 5b2202e..367e4e6 100644
--- a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
@@ -74,22 +74,13 @@
             _serviceName = serviceName;
         }
 
-        /**
-         * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
-         * Args:
-         *   tMessage     The original message.
-         */
-
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
         {
             switch (message.Type)
             {
                 case TMessageType.Call:
                 case TMessageType.Oneway:
-                    await
-                        base.WriteMessageBeginAsync(
-                            new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID),
-                            cancellationToken);
+                    await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken);
                     break;
                 default:
                     await base.WriteMessageBeginAsync(message, cancellationToken);
@@ -97,4 +88,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Protocols/TProtocol.cs b/lib/netcore/Thrift/Protocols/TProtocol.cs
index 8fef861..91e009d 100644
--- a/lib/netcore/Thrift/Protocols/TProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -27,7 +27,7 @@
     // ReSharper disable once InconsistentNaming
     public abstract class TProtocol : IDisposable
     {
-        private const int DefaultRecursionDepth = 64;
+        public const int DefaultRecursionDepth = 64;
         private bool _isDisposed;
         protected int RecursionDepth;
 
@@ -42,7 +42,6 @@
 
         public TClientTransport Transport => Trans;
 
-        //TODO: check for protected
         protected int RecursionLimit { get; set; }
 
         public void Dispose()
@@ -93,12 +92,12 @@
 
         public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken);
 
-        public virtual async Task WriteStructBeginAsync(TStruct struc)
+        public virtual async Task WriteStructBeginAsync(TStruct @struct)
         {
-            await WriteStructBeginAsync(struc, CancellationToken.None);
+            await WriteStructBeginAsync(@struct, CancellationToken.None);
         }
 
-        public abstract Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken);
+        public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken);
 
         public virtual async Task WriteStructEndAsync()
         {
@@ -223,12 +222,12 @@
             await WriteBinaryAsync(bytes, cancellationToken);
         }
 
-        public virtual async Task WriteBinaryAsync(byte[] b)
+        public virtual async Task WriteBinaryAsync(byte[] bytes)
         {
-            await WriteBinaryAsync(b, CancellationToken.None);
+            await WriteBinaryAsync(bytes, CancellationToken.None);
         }
 
-        public abstract Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken);
+        public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken);
 
         public virtual async Task<TMessage> ReadMessageBeginAsync()
         {
diff --git a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs b/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
index 458b117..3222754 100644
--- a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -36,12 +36,7 @@
         protected TProtocolDecorator(TProtocol protocol)
             : base(protocol.Transport)
         {
-            if (protocol == null)
-            {
-                throw new ArgumentNullException(nameof(protocol));
-            }
-
-            _wrappedProtocol = protocol;
+            _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol));
         }
 
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
@@ -54,9 +49,9 @@
             await _wrappedProtocol.WriteMessageEndAsync(cancellationToken);
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
-            await _wrappedProtocol.WriteStructBeginAsync(struc, cancellationToken);
+            await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken);
         }
 
         public override async Task WriteStructEndAsync(CancellationToken cancellationToken)
@@ -144,9 +139,9 @@
             await _wrappedProtocol.WriteStringAsync(s, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
-            await _wrappedProtocol.WriteBinaryAsync(b, cancellationToken);
+            await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken);
         }
 
         public override async Task<TMessage> ReadMessageBeginAsync(CancellationToken cancellationToken)
diff --git a/lib/netcore/Thrift/Protocols/TProtocolException.cs b/lib/netcore/Thrift/Protocols/TProtocolException.cs
index 02d0d3f..8c67c3b 100644
--- a/lib/netcore/Thrift/Protocols/TProtocolException.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocolException.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -15,11 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+// ReSharper disable InconsistentNaming
 namespace Thrift.Protocols
 {
     public class TProtocolException : TException
     {
-        // do not rename public contants - they used in generated files
+        // do not rename public constants - they used in generated files
         public const int UNKNOWN = 0;
         public const int INVALID_DATA = 1;
         public const int NEGATIVE_SIZE = 2;
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs b/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs
new file mode 100644
index 0000000..7eff5e1
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs
@@ -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.
+
+using System;
+
+namespace Thrift.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    internal static class TBase64Helper
+    {
+        //TODO: Constants
+        //TODO: Check for args
+        //TODO: Unitests
+
+        internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+        private static readonly int[] DecodeTable =
+        {
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+            -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+        };
+
+        internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff)
+        {
+            if (src == null)
+            {
+                throw new ArgumentNullException(nameof(src));
+            }
+
+            dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F];
+
+            if (len == 3)
+            {
+                dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)];
+                dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F];
+            }
+            else if (len == 2)
+            {
+                dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C];
+            }
+            else
+            {
+                // len == 1
+                dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30];
+            }
+        }
+
+        internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff)
+        {
+            if (src == null)
+            {
+                throw new ArgumentNullException(nameof(src));
+            }
+
+            dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4));
+
+            if (len > 2)
+            {
+                dst[dstOff + 1] =
+                    (byte)
+                    (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2));
+                if (len > 3)
+                {
+                    dst[dstOff + 2] =
+                        (byte)
+                        (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs
new file mode 100644
index 0000000..93eff78
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs
@@ -0,0 +1,61 @@
+// 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.
+
+namespace Thrift.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    public static class TJSONProtocolConstants
+    {
+        //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/)
+        // can be possible to get better performance and also better GC
+
+        public static readonly byte[] Comma = {(byte) ','};
+        public static readonly byte[] Colon = {(byte) ':'};
+        public static readonly byte[] LeftBrace = {(byte) '{'};
+        public static readonly byte[] RightBrace = {(byte) '}'};
+        public static readonly byte[] LeftBracket = {(byte) '['};
+        public static readonly byte[] RightBracket = {(byte) ']'};
+        public static readonly byte[] Quote = {(byte) '"'};
+        public static readonly byte[] Backslash = {(byte) '\\'};
+
+        public static readonly byte[] JsonCharTable =
+        {
+            0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+        };
+
+        public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray();
+        public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'};
+        public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'};
+
+        public static class TypeNames
+        {
+            public static readonly byte[] NameBool = { (byte)'t', (byte)'f' };
+            public static readonly byte[] NameByte = { (byte)'i', (byte)'8' };
+            public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' };
+            public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' };
+            public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' };
+            public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' };
+            public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' };
+            public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' };
+            public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' };
+            public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' };
+            public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' };
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs
new file mode 100644
index 0000000..adc26a9
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs
@@ -0,0 +1,176 @@
+// 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.
+
+using Thrift.Protocols.Entities;
+
+namespace Thrift.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    public static class TJSONProtocolHelper
+    {
+        public static byte[] GetTypeNameForTypeId(TType typeId)
+        {
+            switch (typeId)
+            {
+                case TType.Bool:
+                    return TJSONProtocolConstants.TypeNames.NameBool;
+                case TType.Byte:
+                    return TJSONProtocolConstants.TypeNames.NameByte;
+                case TType.I16:
+                    return TJSONProtocolConstants.TypeNames.NameI16;
+                case TType.I32:
+                    return TJSONProtocolConstants.TypeNames.NameI32;
+                case TType.I64:
+                    return TJSONProtocolConstants.TypeNames.NameI64;
+                case TType.Double:
+                    return TJSONProtocolConstants.TypeNames.NameDouble;
+                case TType.String:
+                    return TJSONProtocolConstants.TypeNames.NameString;
+                case TType.Struct:
+                    return TJSONProtocolConstants.TypeNames.NameStruct;
+                case TType.Map:
+                    return TJSONProtocolConstants.TypeNames.NameMap;
+                case TType.Set:
+                    return TJSONProtocolConstants.TypeNames.NameSet;
+                case TType.List:
+                    return TJSONProtocolConstants.TypeNames.NameList;
+                default:
+                    throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
+            }
+        }
+
+        public static TType GetTypeIdForTypeName(byte[] name)
+        {
+            var result = TType.Stop;
+            if (name.Length > 1)
+            {
+                switch (name[0])
+                {
+                    case (byte) 'd':
+                        result = TType.Double;
+                        break;
+                    case (byte) 'i':
+                        switch (name[1])
+                        {
+                            case (byte) '8':
+                                result = TType.Byte;
+                                break;
+                            case (byte) '1':
+                                result = TType.I16;
+                                break;
+                            case (byte) '3':
+                                result = TType.I32;
+                                break;
+                            case (byte) '6':
+                                result = TType.I64;
+                                break;
+                        }
+                        break;
+                    case (byte) 'l':
+                        result = TType.List;
+                        break;
+                    case (byte) 'm':
+                        result = TType.Map;
+                        break;
+                    case (byte) 'r':
+                        result = TType.Struct;
+                        break;
+                    case (byte) 's':
+                        if (name[1] == (byte) 't')
+                        {
+                            result = TType.String;
+                        }
+                        else if (name[1] == (byte) 'e')
+                        {
+                            result = TType.Set;
+                        }
+                        break;
+                    case (byte) 't':
+                        result = TType.Bool;
+                        break;
+                }
+            }
+            if (result == TType.Stop)
+            {
+                throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
+            }
+            return result;
+        }
+
+        /// <summary>
+        ///     Return true if the given byte could be a valid part of a JSON number.
+        /// </summary>
+        public static bool IsJsonNumeric(byte b)
+        {
+            switch (b)
+            {
+                case (byte)'+':
+                case (byte)'-':
+                case (byte)'.':
+                case (byte)'0':
+                case (byte)'1':
+                case (byte)'2':
+                case (byte)'3':
+                case (byte)'4':
+                case (byte)'5':
+                case (byte)'6':
+                case (byte)'7':
+                case (byte)'8':
+                case (byte)'9':
+                case (byte)'E':
+                case (byte)'e':
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        /// <summary>
+        ///     Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
+        ///     corresponding hex value
+        /// </summary>
+        public static byte ToHexVal(byte ch)
+        {
+            if (ch >= '0' && ch <= '9')
+            {
+                return (byte)((char)ch - '0');
+            }
+
+            if (ch >= 'a' && ch <= 'f')
+            {
+                ch += 10;
+                return (byte)((char)ch - 'a');
+            }
+
+            throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character");
+        }
+
+        /// <summary>
+        ///     Convert a byte containing a hex value to its corresponding hex character
+        /// </summary>
+        public static byte ToHexChar(byte val)
+        {
+            val &= 0x0F;
+            if (val < 10)
+            {
+                return (byte)((char)val + '0');
+            }
+            val -= 10;
+            return (byte)((char)val + 'a');
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs b/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
index 038edb9..50b0385 100644
--- a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
+++ b/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
@@ -19,83 +19,83 @@
 using System.Threading.Tasks;
 using Thrift.Protocols.Entities;
 
-namespace Thrift.Protocols
+namespace Thrift.Protocols.Utilities
 {
     // ReSharper disable once InconsistentNaming
     public static class TProtocolUtil
     {
-        public static async Task SkipAsync(TProtocol prot, TType type, CancellationToken cancellationToken)
+        public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 await Task.FromCanceled(cancellationToken);
             }
 
-            prot.IncrementRecursionDepth();
+            protocol.IncrementRecursionDepth();
             try
             {
                 switch (type)
                 {
                     case TType.Bool:
-                        await prot.ReadBoolAsync(cancellationToken);
+                        await protocol.ReadBoolAsync(cancellationToken);
                         break;
                     case TType.Byte:
-                        await prot.ReadByteAsync(cancellationToken);
+                        await protocol.ReadByteAsync(cancellationToken);
                         break;
                     case TType.I16:
-                        await prot.ReadI16Async(cancellationToken);
+                        await protocol.ReadI16Async(cancellationToken);
                         break;
                     case TType.I32:
-                        await prot.ReadI32Async(cancellationToken);
+                        await protocol.ReadI32Async(cancellationToken);
                         break;
                     case TType.I64:
-                        await prot.ReadI64Async(cancellationToken);
+                        await protocol.ReadI64Async(cancellationToken);
                         break;
                     case TType.Double:
-                        await prot.ReadDoubleAsync(cancellationToken);
+                        await protocol.ReadDoubleAsync(cancellationToken);
                         break;
                     case TType.String:
                         // Don't try to decode the string, just skip it.
-                        await prot.ReadBinaryAsync(cancellationToken);
+                        await protocol.ReadBinaryAsync(cancellationToken);
                         break;
                     case TType.Struct:
-                        await prot.ReadStructBeginAsync(cancellationToken);
+                        await protocol.ReadStructBeginAsync(cancellationToken);
                         while (true)
                         {
-                            var field = await prot.ReadFieldBeginAsync(cancellationToken);
+                            var field = await protocol.ReadFieldBeginAsync(cancellationToken);
                             if (field.Type == TType.Stop)
                             {
                                 break;
                             }
-                            await SkipAsync(prot, field.Type, cancellationToken);
-                            await prot.ReadFieldEndAsync(cancellationToken);
+                            await SkipAsync(protocol, field.Type, cancellationToken);
+                            await protocol.ReadFieldEndAsync(cancellationToken);
                         }
-                        await prot.ReadStructEndAsync(cancellationToken);
+                        await protocol.ReadStructEndAsync(cancellationToken);
                         break;
                     case TType.Map:
-                        var map = await prot.ReadMapBeginAsync(cancellationToken);
+                        var map = await protocol.ReadMapBeginAsync(cancellationToken);
                         for (var i = 0; i < map.Count; i++)
                         {
-                            await SkipAsync(prot, map.KeyType, cancellationToken);
-                            await SkipAsync(prot, map.ValueType, cancellationToken);
+                            await SkipAsync(protocol, map.KeyType, cancellationToken);
+                            await SkipAsync(protocol, map.ValueType, cancellationToken);
                         }
-                        await prot.ReadMapEndAsync(cancellationToken);
+                        await protocol.ReadMapEndAsync(cancellationToken);
                         break;
                     case TType.Set:
-                        var set = await prot.ReadSetBeginAsync(cancellationToken);
+                        var set = await protocol.ReadSetBeginAsync(cancellationToken);
                         for (var i = 0; i < set.Count; i++)
                         {
-                            await SkipAsync(prot, set.ElementType, cancellationToken);
+                            await SkipAsync(protocol, set.ElementType, cancellationToken);
                         }
-                        await prot.ReadSetEndAsync(cancellationToken);
+                        await protocol.ReadSetEndAsync(cancellationToken);
                         break;
                     case TType.List:
-                        var list = await prot.ReadListBeginAsync(cancellationToken);
+                        var list = await protocol.ReadListBeginAsync(cancellationToken);
                         for (var i = 0; i < list.Count; i++)
                         {
-                            await SkipAsync(prot, list.ElementType, cancellationToken);
+                            await SkipAsync(protocol, list.ElementType, cancellationToken);
                         }
-                        await prot.ReadListEndAsync(cancellationToken);
+                        await protocol.ReadListEndAsync(cancellationToken);
                         break;
                     default:
                         throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
@@ -103,8 +103,8 @@
             }
             finally
             {
-                prot.DecrementRecursionDepth();
+                protocol.DecrementRecursionDepth();
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Server/AsyncBaseServer.cs b/lib/netcore/Thrift/Server/AsyncBaseServer.cs
index 5ff7a32..325c39c 100644
--- a/lib/netcore/Thrift/Server/AsyncBaseServer.cs
+++ b/lib/netcore/Thrift/Server/AsyncBaseServer.cs
@@ -57,8 +57,7 @@
             try
             {
                 // cancelation token
-                _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken),
-                    TaskCreationOptions.LongRunning);
+                _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken), TaskCreationOptions.LongRunning);
                 await _serverTask;
             }
             catch (Exception ex)
@@ -87,7 +86,7 @@
                     try
                     {
                         var client = await ServerTransport.AcceptAsync(cancellationToken);
-                        await Task.Factory.StartNew(() => Execute(client, cancellationToken));
+                        await Task.Factory.StartNew(() => Execute(client, cancellationToken), cancellationToken);
                     }
                     catch (TTransportException ttx)
                     {
@@ -101,7 +100,11 @@
                 }
                 else
                 {
-                    await Task.Delay(TimeSpan.FromMilliseconds(_clientWaitingDelay), cancellationToken);
+                    try
+                    {
+                        await Task.Delay(TimeSpan.FromMilliseconds(_clientWaitingDelay), cancellationToken);
+                    }
+                    catch(TaskCanceledException) { }
                 }
             }
 
@@ -136,8 +139,7 @@
 
                 if (ServerEventHandler != null)
                 {
-                    connectionContext =
-                        await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken);
+                    connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken);
                 }
 
                 while (!cancellationToken.IsCancellationRequested)
@@ -149,8 +151,7 @@
 
                     if (ServerEventHandler != null)
                     {
-                        await
-                            ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken);
+                        await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken);
                     }
 
                     if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken))
@@ -170,9 +171,7 @@
 
             if (ServerEventHandler != null)
             {
-                await
-                    ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol,
-                        cancellationToken);
+                await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken);
             }
 
             inputTransport?.Close();
@@ -181,4 +180,4 @@
             Logger.LogTrace("Completed client request processing");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Server/TBaseServer.cs b/lib/netcore/Thrift/Server/TBaseServer.cs
index 97cc7ff..741dd5c 100644
--- a/lib/netcore/Thrift/Server/TBaseServer.cs
+++ b/lib/netcore/Thrift/Server/TBaseServer.cs
@@ -42,20 +42,13 @@
             ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory,
             ILogger logger)
         {
-            if (itProcessorFactory == null) throw new ArgumentNullException(nameof(itProcessorFactory));
-            if (inputTransportFactory == null) throw new ArgumentNullException(nameof(inputTransportFactory));
-            if (outputTransportFactory == null) throw new ArgumentNullException(nameof(outputTransportFactory));
-            if (inputProtocolFactory == null) throw new ArgumentNullException(nameof(inputProtocolFactory));
-            if (outputProtocolFactory == null) throw new ArgumentNullException(nameof(outputProtocolFactory));
-            if (logger == null) throw new ArgumentNullException(nameof(logger));
-
-            ItProcessorFactory = itProcessorFactory;
+            ItProcessorFactory = itProcessorFactory ?? throw new ArgumentNullException(nameof(itProcessorFactory));
             ServerTransport = serverTransport;
-            InputTransportFactory = inputTransportFactory;
-            OutputTransportFactory = outputTransportFactory;
-            InputProtocolFactory = inputProtocolFactory;
-            OutputProtocolFactory = outputProtocolFactory;
-            Logger = logger;
+            InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory));
+            OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory));
+            InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory));
+            OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory));
+            Logger = logger ?? throw new ArgumentNullException(nameof(logger));
         }
 
         public void SetEventHandler(TServerEventHandler seh)
diff --git a/lib/netcore/Thrift/TApplicationException.cs b/lib/netcore/Thrift/TApplicationException.cs
index f1ea252..9ec145a 100644
--- a/lib/netcore/Thrift/TApplicationException.cs
+++ b/lib/netcore/Thrift/TApplicationException.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -19,6 +19,7 @@
 using System.Threading.Tasks;
 using Thrift.Protocols;
 using Thrift.Protocols.Entities;
+using Thrift.Protocols.Utilities;
 
 namespace Thrift
 {
@@ -60,15 +61,15 @@
             Type = type;
         }
 
-        public static async Task<TApplicationException> ReadAsync(TProtocol iprot, CancellationToken cancellationToken)
+        public static async Task<TApplicationException> ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken)
         {
             string message = null;
             var type = ExceptionType.Unknown;
 
-            await iprot.ReadStructBeginAsync(cancellationToken);
+            await inputProtocol.ReadStructBeginAsync(cancellationToken);
             while (true)
             {
-                var field = await iprot.ReadFieldBeginAsync(cancellationToken);
+                var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken);
                 if (field.Type == TType.Stop)
                 {
                     break;
@@ -79,37 +80,37 @@
                     case MessageTypeFieldId:
                         if (field.Type == TType.String)
                         {
-                            message = await iprot.ReadStringAsync(cancellationToken);
+                            message = await inputProtocol.ReadStringAsync(cancellationToken);
                         }
                         else
                         {
-                            await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                            await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         }
                         break;
                     case ExTypeFieldId:
                         if (field.Type == TType.I32)
                         {
-                            type = (ExceptionType) await iprot.ReadI32Async(cancellationToken);
+                            type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken);
                         }
                         else
                         {
-                            await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                            await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         }
                         break;
                     default:
-                        await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                        await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         break;
                 }
 
-                await iprot.ReadFieldEndAsync(cancellationToken);
+                await inputProtocol.ReadFieldEndAsync(cancellationToken);
             }
 
-            await iprot.ReadStructEndAsync(cancellationToken);
+            await inputProtocol.ReadStructEndAsync(cancellationToken);
 
             return new TApplicationException(type, message);
         }
 
-        public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)
+        public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -123,27 +124,27 @@
             var struc = new TStruct(structApplicationExceptionName);
             var field = new TField();
 
-            await oprot.WriteStructBeginAsync(struc, cancellationToken);
+            await outputProtocol.WriteStructBeginAsync(struc, cancellationToken);
 
             if (!string.IsNullOrEmpty(Message))
             {
                 field.Name = messageTypeFieldName;
                 field.Type = TType.String;
                 field.ID = MessageTypeFieldId;
-                await oprot.WriteFieldBeginAsync(field, cancellationToken);
-                await oprot.WriteStringAsync(Message, cancellationToken);
-                await oprot.WriteFieldEndAsync(cancellationToken);
+                await outputProtocol.WriteFieldBeginAsync(field, cancellationToken);
+                await outputProtocol.WriteStringAsync(Message, cancellationToken);
+                await outputProtocol.WriteFieldEndAsync(cancellationToken);
             }
 
             field.Name = exTypeFieldName;
             field.Type = TType.I32;
             field.ID = ExTypeFieldId;
 
-            await oprot.WriteFieldBeginAsync(field, cancellationToken);
-            await oprot.WriteI32Async((int) Type, cancellationToken);
-            await oprot.WriteFieldEndAsync(cancellationToken);
-            await oprot.WriteFieldStopAsync(cancellationToken);
-            await oprot.WriteStructEndAsync(cancellationToken);
+            await outputProtocol.WriteFieldBeginAsync(field, cancellationToken);
+            await outputProtocol.WriteI32Async((int) Type, cancellationToken);
+            await outputProtocol.WriteFieldEndAsync(cancellationToken);
+            await outputProtocol.WriteFieldStopAsync(cancellationToken);
+            await outputProtocol.WriteStructEndAsync(cancellationToken);
         }
     }
 }
\ No newline at end of file
diff --git a/lib/netcore/Thrift/TBaseClient.cs b/lib/netcore/Thrift/TBaseClient.cs
index ca403e5..e019251 100644
--- a/lib/netcore/Thrift/TBaseClient.cs
+++ b/lib/netcore/Thrift/TBaseClient.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -16,14 +16,13 @@
 // under the License.
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Thrift.Protocols;
 
 namespace Thrift
 {
+    // ReSharper disable once InconsistentNaming
     /// <summary>
     ///     TBaseClient.
     ///     Base client for generated clients.
@@ -39,18 +38,8 @@
 
         protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol)
         {
-            if (inputProtocol == null)
-            {
-                throw new ArgumentNullException(nameof(inputProtocol));
-            }
-
-            if (outputProtocol == null)
-            {
-                throw new ArgumentNullException(nameof(outputProtocol));
-            }
-
-            _inputProtocol = inputProtocol;
-            _outputProtocol = outputProtocol;
+            _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol));
+            _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol));
         }
 
         public TProtocol InputProtocol => _inputProtocol;
diff --git a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
index 86eb735..761f1ac 100644
--- a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -34,17 +34,12 @@
         //TODO: should support only specified input transport?
         public TBufferedClientTransport(TClientTransport transport, int bufSize = 1024)
         {
-            if (transport == null)
-            {
-                throw new ArgumentNullException(nameof(transport));
-            }
-
             if (bufSize <= 0)
             {
                 throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number.");
             }
 
-            _transport = transport;
+            _transport = transport ?? throw new ArgumentNullException(nameof(transport));
             _bufSize = bufSize;
         }
 
@@ -200,8 +195,9 @@
             {
                 if (disposing)
                 {
-                    _inputBuffer.Dispose();
-                    _outputBuffer.Dispose();
+                    _inputBuffer?.Dispose();
+                    _outputBuffer?.Dispose();
+                    _transport?.Dispose();
                 }
             }
             _isDisposed = true;
diff --git a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
index f54a42a..d11bb95 100644
--- a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -37,12 +37,7 @@
 
         public TFramedClientTransport(TClientTransport transport)
         {
-            if (transport == null)
-            {
-                throw new ArgumentNullException(nameof(transport));
-            }
-
-            _transport = transport;
+            _transport = transport ?? throw new ArgumentNullException(nameof(transport));
 
             InitWriteBuffer();
         }
@@ -195,8 +190,9 @@
             {
                 if (disposing)
                 {
-                    _readBuffer.Dispose();
-                    _writeBuffer.Dispose();
+                    _readBuffer?.Dispose();
+                    _writeBuffer?.Dispose();
+                    _transport?.Dispose();
                 }
             }
             _isDisposed = true;
diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
index 1e83f97..797d380 100644
--- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
@@ -16,11 +16,9 @@
 // under the License.
 
 using System;
-using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Security.Cryptography.X509Certificates;
@@ -151,7 +149,7 @@
             }
 
             httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift"));
-            httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.11.0"));
+            httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "1.0.0"));
 
             if (CustomHeaders != null)
             {
@@ -198,7 +196,7 @@
                 {
                     throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString());
                 }
-                catch (WebException wx)
+                catch (HttpRequestException wx)
                 {
                     throw new TTransportException(TTransportException.ExceptionType.Unknown,
                         "Couldn't connect to server: " + wx);
@@ -225,4 +223,4 @@
             _isDisposed = true;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
index a44efe6..e769d14 100644
--- a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
@@ -30,12 +30,7 @@
 
         public TSocketClientTransport(TcpClient client)
         {
-            if (client == null)
-            {
-                throw new ArgumentNullException(nameof(client));
-            }
-
-            TcpClient = client;
+            TcpClient = client ?? throw new ArgumentNullException(nameof(client));
 
             if (IsOpen)
             {
diff --git a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
index a21977b..c8be4ed 100644
--- a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -57,7 +57,7 @@
             if (isServer && certificate == null)
             {
                 throw new ArgumentException("TTlsSocketClientTransport needs certificate to be used for server",
-                    "certificate");
+                    nameof(certificate));
             }
 
             if (IsOpen)
@@ -204,7 +204,8 @@
                         ? new X509CertificateCollection {_certificate}
                         : new X509CertificateCollection();
 
-                    await _secureStream.AuthenticateAsClientAsync(_host.ToString(), certs, _sslProtocols, true);
+                    var targetHost = _host.ToString();
+                    await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true);
                 }
             }
             catch (Exception)
diff --git a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs b/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
index 6073741..032063a 100644
--- a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
@@ -53,29 +53,14 @@
         public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputProtocolFactory,
             ITProtocolFactory outputProtocolFactory, RequestDelegate next, ILoggerFactory loggerFactory)
         {
-            if (processor == null)
-            {
-                throw new ArgumentNullException(nameof(processor));
-            }
-
-            if (inputProtocolFactory == null)
-            {
-                throw new ArgumentNullException(nameof(inputProtocolFactory));
-            }
-
-            if (outputProtocolFactory == null)
-            {
-                throw new ArgumentNullException(nameof(outputProtocolFactory));
-            }
-
             if (loggerFactory == null)
             {
                 throw new ArgumentNullException(nameof(loggerFactory));
             }
 
-            Processor = processor;
-            InputProtocolFactory = inputProtocolFactory;
-            OutputProtocolFactory = outputProtocolFactory;
+            Processor = processor ?? throw new ArgumentNullException(nameof(processor));
+            InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory));
+            OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory));
 
             _next = next;
             _logger = loggerFactory.CreateLogger<THttpServerTransport>();
diff --git a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs b/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
index 01195d4..186786e 100644
--- a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
index af154ef..3a9d8a1 100644
--- a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
@@ -30,6 +30,7 @@
         private readonly int _clientTimeout;
         private readonly int _port;
         private readonly bool _useBufferedSockets;
+        private readonly bool _useFramedTransport;
         private TcpListener _server;
 
         public TServerSocketTransport(TcpListener listener)
@@ -53,11 +54,17 @@
         {
         }
 
-        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets)
+        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets):
+            this(port, clientTimeout, useBufferedSockets, false)
+        {
+        }
+        
+        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport)
         {
             _port = port;
             _clientTimeout = clientTimeout;
             _useBufferedSockets = useBufferedSockets;
+            _useFramedTransport = useFramedTransport;
             try
             {
                 // Make server socket
@@ -106,7 +113,7 @@
 
             try
             {
-                TSocketClientTransport tSocketTransport = null;
+                TClientTransport tSocketTransport = null;
                 var tcpClient = await _server.AcceptTcpClientAsync();
 
                 try
@@ -118,7 +125,12 @@
 
                     if (_useBufferedSockets)
                     {
-                        return new TBufferedClientTransport(tSocketTransport);
+                        tSocketTransport = new TBufferedClientTransport(tSocketTransport);
+                    }
+
+                    if (_useFramedTransport)
+                    {
+                        tSocketTransport = new TFramedClientTransport(tSocketTransport);
                     }
 
                     return tSocketTransport;
diff --git a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
index 49abdac..759feed 100644
--- a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
@@ -37,6 +37,7 @@
         private readonly X509Certificate2 _serverCertificate;
         private readonly SslProtocols _sslProtocols;
         private readonly bool _useBufferedSockets;
+        private readonly bool _useFramedTransport;
         private TcpListener _server;
 
         public TTlsServerSocketTransport(int port, X509Certificate2 certificate)
@@ -50,6 +51,19 @@
             X509Certificate2 certificate,
             RemoteCertificateValidationCallback clientCertValidator = null,
             LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            SslProtocols sslProtocols = SslProtocols.Tls12) 
+            : this(port, useBufferedSockets, false, certificate,
+                clientCertValidator, localCertificateSelectionCallback, sslProtocols)
+        {
+        }
+        
+        public TTlsServerSocketTransport(
+            int port,
+            bool useBufferedSockets,
+            bool useFramedTransport,
+            X509Certificate2 certificate,
+            RemoteCertificateValidationCallback clientCertValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
             SslProtocols sslProtocols = SslProtocols.Tls12)
         {
             if (!certificate.HasPrivateKey)
@@ -61,6 +75,7 @@
             _port = port;
             _serverCertificate = certificate;
             _useBufferedSockets = useBufferedSockets;
+            _useFramedTransport = useFramedTransport;
             _clientCertValidator = clientCertValidator;
             _localCertificateSelectionCallback = localCertificateSelectionCallback;
             _sslProtocols = sslProtocols;
@@ -122,13 +137,19 @@
 
                 await tTlsSocket.SetupTlsAsync();
 
+                TClientTransport trans = tTlsSocket;
+                
                 if (_useBufferedSockets)
                 {
-                    var trans = new TBufferedClientTransport(tTlsSocket);
-                    return trans;
+                    trans = new TBufferedClientTransport(trans);
                 }
 
-                return tTlsSocket;
+                if (_useFramedTransport)
+                {
+                    trans = new TFramedClientTransport(trans);
+                }
+                
+                return trans;
             }
             catch (Exception ex)
             {
diff --git a/lib/netcore/Thrift/Transports/TClientTransport.cs b/lib/netcore/Thrift/Transports/TClientTransport.cs
index cee0a00..0dd96cb 100644
--- a/lib/netcore/Thrift/Transports/TClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/TClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -26,6 +26,7 @@
     // ReSharper disable once InconsistentNaming
     public abstract class TClientTransport : IDisposable
     {
+        //TODO: think how to avoid peek byte
         private readonly byte[] _peekBuffer = new byte[1];
         private bool _hasPeekByte;
         public abstract bool IsOpen { get; }
diff --git a/lib/netcore/Thrift/Transports/TServerTransport.cs b/lib/netcore/Thrift/Transports/TServerTransport.cs
index d49feb6..0d45a55 100644
--- a/lib/netcore/Thrift/Transports/TServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/TServerTransport.cs
@@ -45,7 +45,7 @@
 
             if (transport == null)
             {
-                throw new TTransportException("AcceptAsync() should not return null");
+                throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null");
             }
 
             return transport;
diff --git a/lib/netcore/build.cmd b/lib/netcore/build.cmd
new file mode 100644
index 0000000..863c4b4
--- /dev/null
+++ b/lib/netcore/build.cmd
@@ -0,0 +1,27 @@
+@echo off
+rem /*
+rem  * Licensed to the Apache Software Foundation (ASF) under one
+rem  * or more contributor license agreements. See the NOTICE file
+rem  * distributed with this work for additional information
+rem  * regarding copyright ownership. The ASF licenses this file
+rem  * to you under the Apache License, Version 2.0 (the
+rem  * "License"); you may not use this file except in compliance
+rem  * with the License. You may obtain a copy of the License at
+rem  *
+rem  *   http://www.apache.org/licenses/LICENSE-2.0
+rem  *
+rem  * Unless required by applicable law or agreed to in writing,
+rem  * software distributed under the License is distributed on an
+rem  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem  * KIND, either express or implied. See the License for the
+rem  * specific language governing permissions and limitations
+rem  * under the License.
+rem  */
+
+setlocal
+
+thrift -version
+dotnet --info
+dotnet build 
+
+:eof
diff --git a/lib/netcore/build.sh b/lib/netcore/build.sh
new file mode 100644
index 0000000..ae18bce
--- /dev/null
+++ b/lib/netcore/build.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+#exit if any command fails
+#set -e
+
+thrift --version
+dotnet --info
+dotnet build 
+
+#revision=${TRAVIS_JOB_ID:=1}  
+#revision=$(printf "%04d" $revision) 
+
+#dotnet pack ./src/PROJECT_NAME -c Release -o ./artifacts --version-suffix=$revision  
diff --git a/lib/netcore/runtests.cmd b/lib/netcore/runtests.cmd
new file mode 100644
index 0000000..5114bc5
--- /dev/null
+++ b/lib/netcore/runtests.cmd
@@ -0,0 +1,28 @@
+@echo off
+rem /*
+rem  * Licensed to the Apache Software Foundation (ASF) under one
+rem  * or more contributor license agreements. See the NOTICE file
+rem  * distributed with this work for additional information
+rem  * regarding copyright ownership. The ASF licenses this file
+rem  * to you under the Apache License, Version 2.0 (the
+rem  * "License"); you may not use this file except in compliance
+rem  * with the License. You may obtain a copy of the License at
+rem  *
+rem  *   http://www.apache.org/licenses/LICENSE-2.0
+rem  *
+rem  * Unless required by applicable law or agreed to in writing,
+rem  * software distributed under the License is distributed on an
+rem  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem  * KIND, either express or implied. See the License for the
+rem  * specific language governing permissions and limitations
+rem  * under the License.
+rem  */
+setlocal
+
+thrift -version
+dotnet --info
+
+dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj
+dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj
+
+:eof
diff --git a/lib/netcore/runtests.sh b/lib/netcore/runtests.sh
new file mode 100644
index 0000000..a26cc36
--- /dev/null
+++ b/lib/netcore/runtests.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+thrift -version
+dotnet --info
+
+dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj
+dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj
\ No newline at end of file
diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am
index 9a7b4eb..68ea3ea 100755
--- a/lib/nodejs/Makefile.am
+++ b/lib/nodejs/Makefile.am
@@ -27,8 +27,9 @@
 
 precross: deps stubs
 
+# TODO: Lint nodejs lib and gen-code as part of build
 check: deps
-	cd $(top_srcdir) && $(NPM) test && cd lib/nodejs
+	cd $(top_srcdir) && $(NPM) test && $(NPM) run lint-tests && cd lib/nodejs
 
 clean-local:
 	$(RM) -r test/gen-nodejs
diff --git a/lib/nodejs/README.md b/lib/nodejs/README.md
index 8c25380..50acfbd 100644
--- a/lib/nodejs/README.md
+++ b/lib/nodejs/README.md
@@ -22,7 +22,7 @@
 
 ## Compatibility
 
-node version 4 or later is required
+node version 6 or later is required
 
 ## Install
 
@@ -38,25 +38,27 @@
 
 Here is a Cassandra example:
 
-    var thrift = require('thrift'),
-        Cassandra = require('./gen-nodejs/Cassandra')
-        ttypes = require('./gen-nodejs/cassandra_types');
+```js
+var thrift = require('thrift'),
+    Cassandra = require('./gen-nodejs/Cassandra')
+    ttypes = require('./gen-nodejs/cassandra_types');
 
-    var connection = thrift.createConnection("localhost", 9160),
-        client = thrift.createClient(Cassandra, connection);
+var connection = thrift.createConnection("localhost", 9160),
+    client = thrift.createClient(Cassandra, connection);
 
-    connection.on('error', function(err) {
-      console.error(err);
-    });
+connection.on('error', function(err) {
+  console.error(err);
+});
 
-    client.get_slice("Keyspace", "key", new ttypes.ColumnParent({column_family: "ExampleCF"}), new ttypes.SlicePredicate({slice_range: new ttypes.SliceRange({start: '', finish: ''})}), ttypes.ConsistencyLevel.ONE, function(err, data) {
-      if (err) {
-        // handle err
-      } else {
-        // data == [ttypes.ColumnOrSuperColumn, ...]
-      }
-      connection.end();
-    });
+client.get_slice("Keyspace", "key", new ttypes.ColumnParent({column_family: "ExampleCF"}), new ttypes.SlicePredicate({slice_range: new ttypes.SliceRange({start: '', finish: ''})}), ttypes.ConsistencyLevel.ONE, function(err, data) {
+  if (err) {
+    // handle err
+  } else {
+    // data == [ttypes.ColumnOrSuperColumn, ...]
+  }
+  connection.end();
+});
+```
 
 <a name="int64"></a>
 ## Int64
diff --git a/lib/nodejs/lib/thrift/binary_protocol.js b/lib/nodejs/lib/thrift/binary_protocol.js
index 0c0ee50..b57c8c5 100644
--- a/lib/nodejs/lib/thrift/binary_protocol.js
+++ b/lib/nodejs/lib/thrift/binary_protocol.js
@@ -37,6 +37,7 @@
   this.trans = trans;
   this.strictRead = (strictRead !== undefined ? strictRead : false);
   this.strictWrite = (strictWrite !== undefined ? strictWrite : true);
+  this._seqid = null;
 };
 
 TBinaryProtocol.prototype.flush = function() {
@@ -54,7 +55,7 @@
       this.writeI32(seqid);
     }
     // Record client seqid to find callback again
-    if (this._seqid) {
+    if (this._seqid !== null) {
       log.warning('SeqId already set', { 'name': name });
     } else {
       this._seqid = seqid;
@@ -63,7 +64,7 @@
 };
 
 TBinaryProtocol.prototype.writeMessageEnd = function() {
-    if (this._seqid) {
+    if (this._seqid !== null) {
         this._seqid = null;
     } else {
         log.warning('No seqid to unset');
diff --git a/lib/nodejs/lib/thrift/browser.js b/lib/nodejs/lib/thrift/browser.js
index 4593a8f..67ce853 100644
--- a/lib/nodejs/lib/thrift/browser.js
+++ b/lib/nodejs/lib/thrift/browser.js
@@ -32,3 +32,5 @@
 exports.Protocol = exports.TJSONProtocol = require('./json_protocol');
 exports.TBinaryProtocol = require('./binary_protocol');
 exports.TCompactProtocol = require('./compact_protocol');
+
+exports.Int64 = require('node-int64');
diff --git a/lib/nodejs/lib/thrift/buffered_transport.js b/lib/nodejs/lib/thrift/buffered_transport.js
index 13636b5..a9e006e 100644
--- a/lib/nodejs/lib/thrift/buffered_transport.js
+++ b/lib/nodejs/lib/thrift/buffered_transport.js
@@ -33,6 +33,14 @@
   this.onFlush = callback;
 };
 
+TBufferedTransport.prototype.reset = function() {
+  this.inBuf = new Buffer(this.defaultReadBufferSize);
+  this.readCursor = 0;
+  this.writeCursor = 0;
+  this.outBuffers = [];
+  this.outCount = 0;
+}
+
 TBufferedTransport.receiver = function(callback, seqid) {
   var reader = new TBufferedTransport();
 
diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js
index 273339b..9e5c063 100644
--- a/lib/nodejs/lib/thrift/connection.js
+++ b/lib/nodejs/lib/thrift/connection.js
@@ -221,6 +221,11 @@
   });
 
   this.retry_timer = setTimeout(function () {
+    if (self.connection.destroyed) {
+      self.retry_timer = null;
+      return;
+    }
+
     log.debug("Retrying connection...");
 
     self.retry_totaltime += self.retry_delay;
@@ -232,7 +237,11 @@
        return;
     }
 
-    self.connection.connect(self.port, self.host);
+    if (self.path !== undefined) {
+      self.connection.connect(self.path);
+    } else {
+      self.connection.connect(self.port, self.host);
+    }
     self.retry_timer = null;
   }, this.retry_delay);
 };
@@ -246,6 +255,14 @@
   return connection;
 };
 
+exports.createUDSConnection = function(path, options) {
+  var stream = net.createConnection(path);
+  var connection = new Connection(stream, options);
+  connection.path = path;
+
+  return connection;
+};
+
 exports.createSSLConnection = function(host, port, options) {
   if (!('secureProtocol' in options) && !('secureOptions' in options)) {
     options.secureProtocol = "SSLv23_method";
diff --git a/lib/nodejs/lib/thrift/http_connection.js b/lib/nodejs/lib/thrift/http_connection.js
index 5085538..3c2ab0f 100644
--- a/lib/nodejs/lib/thrift/http_connection.js
+++ b/lib/nodejs/lib/thrift/http_connection.js
@@ -59,8 +59,6 @@
  * Initializes a Thrift HttpConnection instance (use createHttpConnection() rather than
  *    instantiating directly).
  * @constructor
- * @param {string} host - The host name or IP to connect to.
- * @param {number} port - The TCP port to connect to.
  * @param {ConnectOptions} options - The configuration options to use.
  * @throws {error} Exceptions other than InputBufferUnderrunError are rethrown
  * @event {error} The "error" event is fired when a Node.js error event occurs during
@@ -71,15 +69,16 @@
  *     semantics implemented over the Node.js http.request() method.
  * @see {@link createHttpConnection}
  */
-var HttpConnection = exports.HttpConnection = function(host, port, options) {
+var HttpConnection = exports.HttpConnection = function(options) {
   //Initialize the emitter base object
   EventEmitter.call(this);
 
   //Set configuration
   var self = this;
   this.options = options || {};
-  this.host = host;
-  this.port = port;
+  this.host = this.options.host;
+  this.port = this.options.port;
+  this.socketPath = this.options.socketPath;
   this.https = this.options.https || false;
   this.transport = this.options.transport || TBufferedTransport;
   this.protocol = this.options.protocol || TBinaryProtocol;
@@ -87,7 +86,8 @@
   //Prepare Node.js options
   this.nodeOptions = {
     host: this.host,
-    port: this.port || 80,
+    port: this.port,
+    socketPath: this.socketPath,
     path: this.options.path || '/',
     method: 'POST',
     headers: this.options.headers || {},
@@ -170,7 +170,7 @@
     var dataLen = 0;
 
     if (response.statusCode !== 200) {
-      this.emit("error", new THTTPException(statusCode, response));
+      this.emit("error", new THTTPException(response));
     }
 
     response.on('error', function (e) {
@@ -238,19 +238,26 @@
  * @see {@link ConnectOptions}
  */
 exports.createHttpConnection = function(host, port, options) {
-  return new HttpConnection(host, port, options);
+  options.host = host;
+  options.port = port || 80;
+  return new HttpConnection(options);
+};
+
+exports.createHttpUDSConnection = function(path, options) {
+  options.socketPath = path;
+  return new HttpConnection(options);
 };
 
 exports.createHttpClient = createClient
 
 
-function THTTPException(statusCode, response) {
+function THTTPException(response) {
   thrift.TApplicationException.call(this);
   Error.captureStackTrace(this, this.constructor);
   this.name = this.constructor.name;
-  this.statusCode = statusCode;
+  this.statusCode = response.statusCode;
   this.response = response;
   this.type = thrift.TApplicationExceptionType.PROTOCOL_ERROR;
   this.message = "Received a response with a bad HTTP status code: " + response.statusCode;
 }
-util.inherits(THTTPException, thrift.TApplicationException);
\ No newline at end of file
+util.inherits(THTTPException, thrift.TApplicationException);
diff --git a/lib/nodejs/lib/thrift/index.js b/lib/nodejs/lib/thrift/index.js
index 020726d..b09953d 100644
--- a/lib/nodejs/lib/thrift/index.js
+++ b/lib/nodejs/lib/thrift/index.js
@@ -27,6 +27,7 @@
 exports.Connection = connection.Connection;
 exports.createClient = connection.createClient;
 exports.createConnection = connection.createConnection;
+exports.createUDSConnection = connection.createUDSConnection;
 exports.createSSLConnection = connection.createSSLConnection;
 exports.createStdIOClient = connection.createStdIOClient;
 exports.createStdIOConnection = connection.createStdIOConnection;
@@ -34,6 +35,7 @@
 var httpConnection = require('./http_connection');
 exports.HttpConnection = httpConnection.HttpConnection;
 exports.createHttpConnection = httpConnection.createHttpConnection;
+exports.createHttpUDSConnection = httpConnection.createHttpUDSConnection;
 exports.createHttpClient = httpConnection.createHttpClient;
 
 var wsConnection = require('./ws_connection');
diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js
index 84c62f2..727a3b2 100644
--- a/lib/nodejs/lib/thrift/json_protocol.js
+++ b/lib/nodejs/lib/thrift/json_protocol.js
@@ -18,7 +18,6 @@
  */
 
 var Int64 = require('node-int64');
-var InputBufferUnderrunError = require('./transport').InputBufferUnderrunError;
 var Thrift = require('./thrift');
 var Type = Thrift.Type;
 var util = require("util");
@@ -738,5 +737,65 @@
  * Method to arbitrarily skip over data
  */
 TJSONProtocol.prototype.skip = function(type) {
-  throw new Error('skip not supported yet');
+    switch (type) {
+    case Type.STOP:
+      return;
+    case Type.BOOL:
+      this.readBool();
+      break;
+    case Type.BYTE:
+      this.readByte();
+      break;
+    case Type.I16:
+      this.readI16();
+      break;
+    case Type.I32:
+      this.readI32();
+      break;
+    case Type.I64:
+      this.readI64();
+      break;
+    case Type.DOUBLE:
+      this.readDouble();
+      break;
+    case Type.STRING:
+      this.readString();
+      break;
+    case Type.STRUCT:
+      this.readStructBegin();
+      while (true) {
+        var r = this.readFieldBegin();
+        if (r.ftype === Type.STOP) {
+          break;
+        }
+        this.skip(r.ftype);
+        this.readFieldEnd();
+      }
+      this.readStructEnd();
+      break;
+    case Type.MAP:
+      var mapBegin = this.readMapBegin();
+      for (var i = 0; i < mapBegin.size; ++i) {
+        this.skip(mapBegin.ktype);
+        this.skip(mapBegin.vtype);
+      }
+      this.readMapEnd();
+      break;
+    case Type.SET:
+      var setBegin = this.readSetBegin();
+      for (var i2 = 0; i2 < setBegin.size; ++i2) {
+        this.skip(setBegin.etype);
+      }
+      this.readSetEnd();
+      break;
+    case Type.LIST:
+      var listBegin = this.readListBegin();
+      for (var i3 = 0; i3 < listBegin.size; ++i3) {
+        this.skip(listBegin.etype);
+      }
+      this.readListEnd();
+      break;
+    default:
+      throw new  Error("Invalid type: " + type);
+  }
 };
diff --git a/lib/nodejs/lib/thrift/web_server.js b/lib/nodejs/lib/thrift/web_server.js
index 0093c8a..a33f47a 100644
--- a/lib/nodejs/lib/thrift/web_server.js
+++ b/lib/nodejs/lib/thrift/web_server.js
@@ -415,7 +415,15 @@
 
     //Locate the file requested and send it
     var uri = url.parse(request.url).pathname;
-    var filename = path.join(baseDir, uri);
+    var filename = path.resolve(path.join(baseDir, uri));
+
+    //Ensure the basedir path is not able to be escaped
+    if (filename.indexOf(baseDir) != 0) {
+      response.writeHead(400, "Invalid request path", {});
+      response.end();
+      return;
+    }
+
     fs.exists(filename, function(exists) {
       if(!exists) {
         response.writeHead(404);
diff --git a/lib/nodejs/test/binary.test.js b/lib/nodejs/test/binary.test.js
index 38ba634..187cd18 100644
--- a/lib/nodejs/test/binary.test.js
+++ b/lib/nodejs/test/binary.test.js
@@ -17,19 +17,19 @@
  * under the License.
  */
 
-var test = require('tape');
-var binary = require('thrift/binary');
+const test = require("tape");
+const binary = require("thrift/binary");
 
-var cases = {
-  "Should read signed byte": function(assert){
+const cases = {
+  "Should read signed byte": function(assert) {
     assert.equal(1, binary.readByte(0x01));
-    assert.equal(-1, binary.readByte(0xFF));
+    assert.equal(-1, binary.readByte(0xff));
 
-    assert.equal(127, binary.readByte(0x7F));
+    assert.equal(127, binary.readByte(0x7f));
     assert.equal(-128, binary.readByte(0x80));
     assert.end();
   },
-  "Should write byte": function(assert){
+  "Should write byte": function(assert) {
     //Protocol simply writes to the buffer. Nothing to test.. yet.
     assert.ok(true);
     assert.end();
@@ -76,58 +76,135 @@
     assert.deepEqual([0xff, 0xff, 0xff, 0xff], binary.writeI32([], -1));
 
     // Min I32
-    assert.deepEqual([0x80, 0x00, 0x00, 0x00], binary.writeI32([], -2147483648));
+    assert.deepEqual(
+      [0x80, 0x00, 0x00, 0x00],
+      binary.writeI32([], -2147483648)
+    );
     // Max I32
     assert.deepEqual([0x7f, 0xff, 0xff, 0xff], binary.writeI32([], 2147483647));
     assert.end();
   },
 
   "Should read doubles": function(assert) {
-    assert.equal(0, binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-    assert.equal(0, binary.readDouble([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-    assert.equal(1, binary.readDouble([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-    assert.equal(2, binary.readDouble([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-    assert.equal(-2, binary.readDouble([0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
+    assert.equal(
+      0,
+      binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
+    assert.equal(
+      0,
+      binary.readDouble([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
+    assert.equal(
+      1,
+      binary.readDouble([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
+    assert.equal(
+      2,
+      binary.readDouble([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
+    assert.equal(
+      -2,
+      binary.readDouble([0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
 
-    assert.equal(Math.PI, binary.readDouble([0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18]))
+    assert.equal(
+      Math.PI,
+      binary.readDouble([0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18])
+    );
 
-    assert.equal(Infinity, binary.readDouble([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-    assert.equal(-Infinity, binary.readDouble([0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
+    assert.equal(
+      Infinity,
+      binary.readDouble([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
+    assert.equal(
+      -Infinity,
+      binary.readDouble([0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
 
-    assert.ok(isNaN(binary.readDouble([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])))
+    assert.ok(
+      isNaN(binary.readDouble([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
+    );
 
-    assert.equal(1/3, binary.readDouble([0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55]))
+    assert.equal(
+      1 / 3,
+      binary.readDouble([0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55])
+    );
 
     // Min subnormal positive double
-    assert.equal(4.9406564584124654e-324, binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]))
+    assert.equal(
+      4.9406564584124654e-324,
+      binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])
+    );
     // Min normal positive double
-    assert.equal(2.2250738585072014e-308, binary.readDouble([0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
+    assert.equal(
+      2.2250738585072014e-308,
+      binary.readDouble([0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+    );
     // Max positive double
-    assert.equal(1.7976931348623157e308, binary.readDouble([0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]))
+    assert.equal(
+      1.7976931348623157e308,
+      binary.readDouble([0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
+    );
     assert.end();
   },
 
   "Should write doubles": function(assert) {
-    assert.deepEqual([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 0));
-    assert.deepEqual([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 1));
-    assert.deepEqual([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 2));
-    assert.deepEqual([0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], -2));
+    assert.deepEqual(
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], 0)
+    );
+    assert.deepEqual(
+      [0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], 1)
+    );
+    assert.deepEqual(
+      [0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], 2)
+    );
+    assert.deepEqual(
+      [0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], -2)
+    );
 
-    assert.deepEqual([0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], binary.writeDouble([], Math.PI));
+    assert.deepEqual(
+      [0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18],
+      binary.writeDouble([], Math.PI)
+    );
 
-    assert.deepEqual([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], Infinity));
-    assert.deepEqual([0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], -Infinity));
+    assert.deepEqual(
+      [0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], Infinity)
+    );
+    assert.deepEqual(
+      [0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], -Infinity)
+    );
 
-    assert.deepEqual([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], NaN));
+    assert.deepEqual(
+      [0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], NaN)
+    );
 
-    assert.deepEqual([0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55], binary.writeDouble([], 1/3));
+    assert.deepEqual(
+      [0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55],
+      binary.writeDouble([], 1 / 3)
+    );
 
     // Min subnormal positive double
-    assert.deepEqual([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], binary.writeDouble([], 4.9406564584124654e-324));
+    assert.deepEqual(
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
+      binary.writeDouble([], 4.9406564584124654e-324)
+    );
     // Min normal positive double
-    assert.deepEqual([0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 2.2250738585072014e-308));
+    assert.deepEqual(
+      [0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+      binary.writeDouble([], 2.2250738585072014e-308)
+    );
     // Max positive double
-    assert.deepEqual([0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], binary.writeDouble([], 1.7976931348623157e308));
+    assert.deepEqual(
+      [0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+      binary.writeDouble([], 1.7976931348623157e308)
+    );
     assert.end();
   }
 };
diff --git a/lib/nodejs/test/browser_client.js b/lib/nodejs/test/browser_client.js
deleted file mode 100644
index 72fd837..0000000
--- a/lib/nodejs/test/browser_client.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-
-var assert = require('assert');
-var thrift = require('thrift');
-var helpers = require('./helpers');
-var ThriftTest = require('./gen-nodejs/ThriftTest');
-var ThriftTestDriver = require('./test_driver').ThriftTestDriver;
-
-// createXHRConnection createWSConnection
-var connection = thrift.createXHRConnection("localhost", 9090, {
-    transport: helpers.transports['buffered'],
-    protocol: helpers.protocols['json'],
-    path: '/test'
-});
-
-connection.on('error', function(err) {
-    assert(false, err);
-});
-
-// Uncomment the following line to start a websockets connection
-// connection.open();
-
-// createWSClient createXHRClient
-var client = thrift.createXHRClient(ThriftTest, connection);
-
-ThriftTestDriver(client, function (status) {
-    console.log('Browser:', status);
-});
diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.js
index 006fad2..49e3a5e 100644
--- a/lib/nodejs/test/client.js
+++ b/lib/nodejs/test/client.js
@@ -19,115 +19,149 @@
  * under the License.
  */
 
-var fs = require('fs');
-var assert = require('assert');
-var thrift = require('thrift');
-var helpers = require('./helpers');
-var ThriftTest = require('./gen-nodejs/ThriftTest');
-var ThriftTestDriver = require('./test_driver').ThriftTestDriver;
-var ThriftTestDriverPromise = require('./test_driver').ThriftTestDriverPromise;
-var SecondService = require('./gen-nodejs/SecondService');
-var ttypes = require('./gen-nodejs/ThriftTest_types');
+const assert = require("assert");
+const thrift = require("thrift");
+const helpers = require("./helpers");
 
-var program = require('commander');
+const ThriftTest = require(`./${helpers.genPath}/ThriftTest`);
+const ThriftTestDriver = require("./test_driver").ThriftTestDriver;
+const ThriftTestDriverPromise = require("./test_driver")
+  .ThriftTestDriverPromise;
+const SecondService = require(`./${helpers.genPath}/SecondService`);
+
+const program = require("commander");
 
 program
-  .option('-p, --protocol <protocol>', 'Set thrift protocol (binary|compact|json) [protocol]')
-  .option('-t, --transport <transport>', 'Set thrift transport (buffered|framed|http) [transport]')
-  .option('--port <port>', 'Set thrift server port number to connect', 9090)
-  .option('--host <host>', 'Set thrift server host to connect', 'localhost')
-  .option('--ssl', 'use SSL transport')
-  .option('--promise', 'test with promise style functions')
-  .option('-t, --type <type>', 'Select server type (http|multiplex|tcp|websocket)', 'tcp')
+  .option(
+    "-p, --protocol <protocol>",
+    "Set thrift protocol (binary|compact|json) [protocol]"
+  )
+  .option(
+    "-t, --transport <transport>",
+    "Set thrift transport (buffered|framed|http) [transport]"
+  )
+  .option("--port <port>", "Set thrift server port number to connect", 9090)
+  .option("--host <host>", "Set thrift server host to connect", "localhost")
+  .option(
+    "--domain-socket <path>",
+    "Set thrift server unix domain socket to connect"
+  )
+  .option("--ssl", "use SSL transport")
+  .option("--callback", "test with callback style functions")
+  .option(
+    "-t, --type <type>",
+    "Select server type (http|multiplex|tcp|websocket)",
+    "tcp"
+  )
+  .option("--es6", "Use es6 code")
+  .option("--es5", "Use es5 code")
   .parse(process.argv);
 
-var host = program.host;
-var port = program.port;
-var type = program.type;
-var ssl = program.ssl;
-var promise = program.promise;
+const host = program.host;
+const port = program.port;
+const domainSocket = program.domainSocket;
+const ssl = program.ssl;
+let type = program.type;
 
 /* for compatibility with cross test invocation for http transport testing */
-if (program.transport === 'http') {
-  program.transport = 'buffered';
-  type = 'http';
+if (program.transport === "http") {
+  program.transport = "buffered";
+  type = "http";
 }
 
-var options = {
+const options = {
   transport: helpers.transports[program.transport],
   protocol: helpers.protocols[program.protocol]
 };
 
-if (type === 'http' || type === 'websocket') {
-  options.path = '/test';
+if (type === "http" || type === "websocket") {
+  options.path = "/test";
 }
 
-if (type === 'http') {
-  options.headers = {"Connection": "close"};
+if (type === "http") {
+  options.headers = { Connection: "close" };
 }
 
 if (ssl) {
-  if (type === 'tcp' || type === 'multiplex') {
+  if (type === "tcp" || type === "multiplex") {
     options.rejectUnauthorized = false;
-  } else if (type === 'http') {
+  } else if (type === "http") {
     options.nodeOptions = { rejectUnauthorized: false };
     options.https = true;
-  } else if (type === 'websocket') {
+  } else if (type === "websocket") {
     options.wsOptions = { rejectUnauthorized: false };
     options.secure = true;
   }
 }
 
-var connection;
-var client;
-var testDriver = promise ? ThriftTestDriverPromise : ThriftTestDriver;
+let connection;
+let client;
+const testDriver = program.callback
+  ? ThriftTestDriver
+  : ThriftTestDriverPromise;
+if (helpers.ecmaMode === "es6" && program.callback) {
+  console.log("ES6 does not support callback style");
+  process.exit(0);
+}
 
-if (type === 'tcp' || type === 'multiplex') {
-  connection = ssl ?
-    thrift.createSSLConnection(host, port, options) :
-    thrift.createConnection(host, port, options);
-} else if (type === 'http') {
-  connection = thrift.createHttpConnection(host, port, options);
-} else if (type === 'websocket') {
+if (type === "tcp" || type === "multiplex") {
+  if (domainSocket) {
+    connection = thrift.createUDSConnection(domainSocket, options);
+  } else {
+    connection = ssl
+      ? thrift.createSSLConnection(host, port, options)
+      : thrift.createConnection(host, port, options);
+  }
+} else if (type === "http") {
+  if (domainSocket) {
+    connection = thrift.createHttpUDSConnection(domainSocket, options);
+  } else {
+    connection = thrift.createHttpConnection(host, port, options);
+  }
+} else if (type === "websocket") {
   connection = thrift.createWSConnection(host, port, options);
   connection.open();
 }
 
-connection.on('error', function(err) {
-    assert(false, err);
+connection.on("error", function(err) {
+  assert(false, err);
 });
 
-if (type === 'tcp') {
+if (type === "tcp") {
   client = thrift.createClient(ThriftTest, connection);
   runTests();
-} else if (type === 'multiplex') {
-  var mp = new thrift.Multiplexer();
+} else if (type === "multiplex") {
+  const mp = new thrift.Multiplexer();
   client = mp.createClient("ThriftTest", ThriftTest, connection);
-  secondclient = mp.createClient("SecondService", SecondService, connection);
+  const secondclient = mp.createClient(
+    "SecondService",
+    SecondService,
+    connection
+  );
 
-  connection.on('connect', function() {
+  connection.on("connect", function() {
     secondclient.secondtestString("Test", function(err, response) {
       assert(!err);
-      assert.equal("testString(\"Test\")", response);
+      assert.equal('testString("Test")', response);
     });
 
     runTests();
   });
-} else if (type === 'http') {
+} else if (type === "http") {
   client = thrift.createHttpClient(ThriftTest, connection);
   runTests();
-} else if (type === 'websocket') {
+} else if (type === "websocket") {
   client = thrift.createWSClient(ThriftTest, connection);
   runTests();
 }
 
 function runTests() {
-  testDriver(client, function (status) {
+  testDriver(client, function(status) {
     console.log(status);
-    if (type !== 'http' && type !== 'websocket') {
+    if (type !== "http" && type !== "websocket") {
       connection.end();
     }
-    if (type !== 'multiplex') {
+    if (type !== "multiplex") {
       process.exit(0);
     }
   });
diff --git a/lib/nodejs/test/deep-constructor.test.js b/lib/nodejs/test/deep-constructor.test.js
index 145b668..504dacf 100644
--- a/lib/nodejs/test/deep-constructor.test.js
+++ b/lib/nodejs/test/deep-constructor.test.js
@@ -17,39 +17,36 @@
  * under the License.
  */
 
-var ttypes = require('./gen-nodejs/JsDeepConstructorTest_types');
-var thrift = require('thrift');
-var test = require('tape');
-var bufferEquals = require('buffer-equals');
+const ttypes = require("./gen-nodejs/JsDeepConstructorTest_types");
+const thrift = require("thrift");
+const test = require("tape");
+const bufferEquals = require("buffer-equals");
 
 function serializeBinary(data) {
-  var buff;
-  var transport = new thrift.TBufferedTransport(null, function(msg){
+  let buff;
+  const transport = new thrift.TBufferedTransport(null, function(msg) {
     buff = msg;
   });
-  var prot = new thrift.TBinaryProtocol(transport);
+  const prot = new thrift.TBinaryProtocol(transport);
   data.write(prot);
   prot.flush();
   return buff;
-
 }
 
-
 function deserializeBinary(serialized, type) {
-  var t = new thrift.TFramedTransport(serialized);
-  var p = new thrift.TBinaryProtocol(t);
-  var data = new type();
+  const t = new thrift.TFramedTransport(serialized);
+  const p = new thrift.TBinaryProtocol(t);
+  const data = new type();
   data.read(p);
   return data;
 }
 
-
 function serializeJSON(data) {
-  var buff;
-  var transport = new thrift.TBufferedTransport(null, function(msg){
+  let buff;
+  const transport = new thrift.TBufferedTransport(null, function(msg) {
     buff = msg;
   });
-  var protocol  = new thrift.TJSONProtocol(transport);
+  const protocol = new thrift.TJSONProtocol(transport);
   protocol.writeMessageBegin("", 0, 0);
   data.write(protocol);
   protocol.writeMessageEnd();
@@ -57,45 +54,41 @@
   return buff;
 }
 
-
 function deserializeJSON(serialized, type) {
-  var transport = new thrift.TFramedTransport(serialized);
-  var protocol  = new thrift.TJSONProtocol(transport);
+  const transport = new thrift.TFramedTransport(serialized);
+  const protocol = new thrift.TJSONProtocol(transport);
   protocol.readMessageBegin();
-  var data = new type();
+  const data = new type();
   data.read(protocol);
   protocol.readMessageEnd();
   return data;
 }
 
-
 function createThriftObj() {
-
   return new ttypes.Complex({
-
-    struct_field: new ttypes.Simple({value: 'a'}),
+    struct_field: new ttypes.Simple({ value: "a" }),
 
     struct_list_field: [
-      new ttypes.Simple({value: 'b'}),
-      new ttypes.Simple({value: 'c'}),
+      new ttypes.Simple({ value: "b" }),
+      new ttypes.Simple({ value: "c" })
     ],
 
     struct_set_field: [
-      new ttypes.Simple({value: 'd'}),
-      new ttypes.Simple({value: 'e'}),
+      new ttypes.Simple({ value: "d" }),
+      new ttypes.Simple({ value: "e" })
     ],
 
     struct_map_field: {
-      A: new ttypes.Simple({value: 'f'}),
-      B: new ttypes.Simple({value: 'g'})
+      A: new ttypes.Simple({ value: "f" }),
+      B: new ttypes.Simple({ value: "g" })
     },
 
     struct_nested_containers_field: [
       [
         {
           C: [
-            new ttypes.Simple({value: 'h'}),
-            new ttypes.Simple({value: 'i'})
+            new ttypes.Simple({ value: "h" }),
+            new ttypes.Simple({ value: "i" })
           ]
         }
       ]
@@ -104,59 +97,57 @@
     struct_nested_containers_field2: {
       D: [
         {
-          DA: new ttypes.Simple({value: 'j'})
+          DA: new ttypes.Simple({ value: "j" })
         },
         {
-          DB: new ttypes.Simple({value: 'k'})
+          DB: new ttypes.Simple({ value: "k" })
         }
       ]
     },
 
     list_of_list_field: [
-      ['l00', 'l01', 'l02'],
-      ['l10', 'l11', 'l12'],
-      ['l20', 'l21', 'l22'],
+      ["l00", "l01", "l02"],
+      ["l10", "l11", "l12"],
+      ["l20", "l21", "l22"]
     ],
 
     list_of_list_of_list_field: [
-      [['m000', 'm001', 'm002'], ['m010', 'm011', 'm012'], ['m020', 'm021', 'm022']],
-      [['m100', 'm101', 'm102'], ['m110', 'm111', 'm112'], ['m120', 'm121', 'm122']],
-      [['m200', 'm201', 'm202'], ['m210', 'm211', 'm212'], ['m220', 'm221', 'm222']],
-    ],
-
-
+      [
+        ["m000", "m001", "m002"],
+        ["m010", "m011", "m012"],
+        ["m020", "m021", "m022"]
+      ],
+      [
+        ["m100", "m101", "m102"],
+        ["m110", "m111", "m112"],
+        ["m120", "m121", "m122"]
+      ],
+      [
+        ["m200", "m201", "m202"],
+        ["m210", "m211", "m212"],
+        ["m220", "m221", "m222"]
+      ]
+    ]
   });
 }
 
-
 function createJsObj() {
-
   return {
+    struct_field: { value: "a" },
 
-    struct_field: {value: 'a'},
+    struct_list_field: [{ value: "b" }, { value: "c" }],
 
-    struct_list_field: [
-      {value: 'b'},
-      {value: 'c'},
-    ],
-
-    struct_set_field: [
-      {value: 'd'},
-      {value: 'e'},
-    ],
+    struct_set_field: [{ value: "d" }, { value: "e" }],
 
     struct_map_field: {
-      A: {value: 'f'},
-      B: {value: 'g'}
+      A: { value: "f" },
+      B: { value: "g" }
     },
 
     struct_nested_containers_field: [
       [
         {
-          C: [
-            {value: 'h'},
-            {value: 'i'}
-          ]
+          C: [{ value: "h" }, { value: "i" }]
         }
       ]
     ],
@@ -164,131 +155,142 @@
     struct_nested_containers_field2: {
       D: [
         {
-          DA: {value: 'j'}
+          DA: { value: "j" }
         },
         {
-          DB: {value: 'k'}
+          DB: { value: "k" }
         }
       ]
     },
 
     list_of_list_field: [
-      ['l00', 'l01', 'l02'],
-      ['l10', 'l11', 'l12'],
-      ['l20', 'l21', 'l22'],
+      ["l00", "l01", "l02"],
+      ["l10", "l11", "l12"],
+      ["l20", "l21", "l22"]
     ],
 
     list_of_list_of_list_field: [
-      [['m000', 'm001', 'm002'], ['m010', 'm011', 'm012'], ['m020', 'm021', 'm022']],
-      [['m100', 'm101', 'm102'], ['m110', 'm111', 'm112'], ['m120', 'm121', 'm122']],
-      [['m200', 'm201', 'm202'], ['m210', 'm211', 'm212'], ['m220', 'm221', 'm222']],
-    ],
-
+      [
+        ["m000", "m001", "m002"],
+        ["m010", "m011", "m012"],
+        ["m020", "m021", "m022"]
+      ],
+      [
+        ["m100", "m101", "m102"],
+        ["m110", "m111", "m112"],
+        ["m120", "m121", "m122"]
+      ],
+      [
+        ["m200", "m201", "m202"],
+        ["m210", "m211", "m212"],
+        ["m220", "m221", "m222"]
+      ]
+    ]
   };
 }
 
-
 function assertValues(obj, assert) {
-    assert.equals(obj.struct_field.value, 'a');
-    assert.equals(obj.struct_list_field[0].value, 'b');
-    assert.equals(obj.struct_list_field[1].value, 'c');
-    assert.equals(obj.struct_set_field[0].value, 'd');
-    assert.equals(obj.struct_set_field[1].value, 'e');
-    assert.equals(obj.struct_map_field.A.value, 'f');
-    assert.equals(obj.struct_map_field.B.value, 'g');
-    assert.equals(obj.struct_nested_containers_field[0][0].C[0].value, 'h');
-    assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, 'i');
-    assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, 'j');
-    assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, 'k');
-    assert.equals(obj.list_of_list_field[0][0], 'l00');
-    assert.equals(obj.list_of_list_field[0][1], 'l01');
-    assert.equals(obj.list_of_list_field[0][2], 'l02');
-    assert.equals(obj.list_of_list_field[1][0], 'l10');
-    assert.equals(obj.list_of_list_field[1][1], 'l11');
-    assert.equals(obj.list_of_list_field[1][2], 'l12');
-    assert.equals(obj.list_of_list_field[2][0], 'l20');
-    assert.equals(obj.list_of_list_field[2][1], 'l21');
-    assert.equals(obj.list_of_list_field[2][2], 'l22');
+  assert.equals(obj.struct_field.value, "a");
+  assert.equals(obj.struct_list_field[0].value, "b");
+  assert.equals(obj.struct_list_field[1].value, "c");
+  assert.equals(obj.struct_set_field[0].value, "d");
+  assert.equals(obj.struct_set_field[1].value, "e");
+  assert.equals(obj.struct_map_field.A.value, "f");
+  assert.equals(obj.struct_map_field.B.value, "g");
+  assert.equals(obj.struct_nested_containers_field[0][0].C[0].value, "h");
+  assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, "i");
+  assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, "j");
+  assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, "k");
+  assert.equals(obj.list_of_list_field[0][0], "l00");
+  assert.equals(obj.list_of_list_field[0][1], "l01");
+  assert.equals(obj.list_of_list_field[0][2], "l02");
+  assert.equals(obj.list_of_list_field[1][0], "l10");
+  assert.equals(obj.list_of_list_field[1][1], "l11");
+  assert.equals(obj.list_of_list_field[1][2], "l12");
+  assert.equals(obj.list_of_list_field[2][0], "l20");
+  assert.equals(obj.list_of_list_field[2][1], "l21");
+  assert.equals(obj.list_of_list_field[2][2], "l22");
 
-    assert.equals(obj.list_of_list_of_list_field[0][0][0], 'm000');
-    assert.equals(obj.list_of_list_of_list_field[0][0][1], 'm001');
-    assert.equals(obj.list_of_list_of_list_field[0][0][2], 'm002');
-    assert.equals(obj.list_of_list_of_list_field[0][1][0], 'm010');
-    assert.equals(obj.list_of_list_of_list_field[0][1][1], 'm011');
-    assert.equals(obj.list_of_list_of_list_field[0][1][2], 'm012');
-    assert.equals(obj.list_of_list_of_list_field[0][2][0], 'm020');
-    assert.equals(obj.list_of_list_of_list_field[0][2][1], 'm021');
-    assert.equals(obj.list_of_list_of_list_field[0][2][2], 'm022');
+  assert.equals(obj.list_of_list_of_list_field[0][0][0], "m000");
+  assert.equals(obj.list_of_list_of_list_field[0][0][1], "m001");
+  assert.equals(obj.list_of_list_of_list_field[0][0][2], "m002");
+  assert.equals(obj.list_of_list_of_list_field[0][1][0], "m010");
+  assert.equals(obj.list_of_list_of_list_field[0][1][1], "m011");
+  assert.equals(obj.list_of_list_of_list_field[0][1][2], "m012");
+  assert.equals(obj.list_of_list_of_list_field[0][2][0], "m020");
+  assert.equals(obj.list_of_list_of_list_field[0][2][1], "m021");
+  assert.equals(obj.list_of_list_of_list_field[0][2][2], "m022");
 
-    assert.equals(obj.list_of_list_of_list_field[1][0][0], 'm100');
-    assert.equals(obj.list_of_list_of_list_field[1][0][1], 'm101');
-    assert.equals(obj.list_of_list_of_list_field[1][0][2], 'm102');
-    assert.equals(obj.list_of_list_of_list_field[1][1][0], 'm110');
-    assert.equals(obj.list_of_list_of_list_field[1][1][1], 'm111');
-    assert.equals(obj.list_of_list_of_list_field[1][1][2], 'm112');
-    assert.equals(obj.list_of_list_of_list_field[1][2][0], 'm120');
-    assert.equals(obj.list_of_list_of_list_field[1][2][1], 'm121');
-    assert.equals(obj.list_of_list_of_list_field[1][2][2], 'm122');
+  assert.equals(obj.list_of_list_of_list_field[1][0][0], "m100");
+  assert.equals(obj.list_of_list_of_list_field[1][0][1], "m101");
+  assert.equals(obj.list_of_list_of_list_field[1][0][2], "m102");
+  assert.equals(obj.list_of_list_of_list_field[1][1][0], "m110");
+  assert.equals(obj.list_of_list_of_list_field[1][1][1], "m111");
+  assert.equals(obj.list_of_list_of_list_field[1][1][2], "m112");
+  assert.equals(obj.list_of_list_of_list_field[1][2][0], "m120");
+  assert.equals(obj.list_of_list_of_list_field[1][2][1], "m121");
+  assert.equals(obj.list_of_list_of_list_field[1][2][2], "m122");
 
-    assert.equals(obj.list_of_list_of_list_field[2][0][0], 'm200');
-    assert.equals(obj.list_of_list_of_list_field[2][0][1], 'm201');
-    assert.equals(obj.list_of_list_of_list_field[2][0][2], 'm202');
-    assert.equals(obj.list_of_list_of_list_field[2][1][0], 'm210');
-    assert.equals(obj.list_of_list_of_list_field[2][1][1], 'm211');
-    assert.equals(obj.list_of_list_of_list_field[2][1][2], 'm212');
-    assert.equals(obj.list_of_list_of_list_field[2][2][0], 'm220');
-    assert.equals(obj.list_of_list_of_list_field[2][2][1], 'm221');
-    assert.equals(obj.list_of_list_of_list_field[2][2][2], 'm222');
+  assert.equals(obj.list_of_list_of_list_field[2][0][0], "m200");
+  assert.equals(obj.list_of_list_of_list_field[2][0][1], "m201");
+  assert.equals(obj.list_of_list_of_list_field[2][0][2], "m202");
+  assert.equals(obj.list_of_list_of_list_field[2][1][0], "m210");
+  assert.equals(obj.list_of_list_of_list_field[2][1][1], "m211");
+  assert.equals(obj.list_of_list_of_list_field[2][1][2], "m212");
+  assert.equals(obj.list_of_list_of_list_field[2][2][0], "m220");
+  assert.equals(obj.list_of_list_of_list_field[2][2][1], "m221");
+  assert.equals(obj.list_of_list_of_list_field[2][2][2], "m222");
 }
 
 function createTestCases(serialize, deserialize) {
-
-  var cases = {
-
-    "Serialize/deserialize should return equal object": function(assert){
-      var tObj = createThriftObj();
-      var received = deserialize(serialize(tObj), ttypes.Complex);
-      assert.ok(tObj !== received, 'not the same object');
+  const cases = {
+    "Serialize/deserialize should return equal object": function(assert) {
+      const tObj = createThriftObj();
+      const received = deserialize(serialize(tObj), ttypes.Complex);
+      assert.ok(tObj !== received, "not the same object");
       assert.deepEqual(tObj, received);
       assert.end();
     },
 
-    "Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects": function(assert) {
-      var tObj1 = createThriftObj();
-      var tObj2 = new ttypes.Complex(createJsObj());
+    "Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects": function(
+      assert
+    ) {
+      const tObj1 = createThriftObj();
+      const tObj2 = new ttypes.Complex(createJsObj());
       assertValues(tObj2, assert);
-      var s1 = serialize(tObj1);
-      var s2 = serialize(tObj2);
+      const s1 = serialize(tObj1);
+      const s2 = serialize(tObj2);
       assert.ok(bufferEquals(s1, s2));
       assert.end();
     },
 
-    "Modifications to args object should not affect constructed Thrift object": function (assert) {
-
-      var args = createJsObj();
+    "Modifications to args object should not affect constructed Thrift object": function(
+      assert
+    ) {
+      const args = createJsObj();
       assertValues(args, assert);
 
-      var tObj = new ttypes.Complex(args);
+      const tObj = new ttypes.Complex(args);
       assertValues(tObj, assert);
 
-      args.struct_field.value = 'ZZZ';
-      args.struct_list_field[0].value = 'ZZZ';
-      args.struct_list_field[1].value = 'ZZZ';
-      args.struct_set_field[0].value = 'ZZZ';
-      args.struct_set_field[1].value = 'ZZZ';
-      args.struct_map_field.A.value = 'ZZZ';
-      args.struct_map_field.B.value = 'ZZZ';
-      args.struct_nested_containers_field[0][0].C[0] = 'ZZZ';
-      args.struct_nested_containers_field[0][0].C[1] = 'ZZZ';
-      args.struct_nested_containers_field2.D[0].DA = 'ZZZ';
-      args.struct_nested_containers_field2.D[0].DB = 'ZZZ';
+      args.struct_field.value = "ZZZ";
+      args.struct_list_field[0].value = "ZZZ";
+      args.struct_list_field[1].value = "ZZZ";
+      args.struct_set_field[0].value = "ZZZ";
+      args.struct_set_field[1].value = "ZZZ";
+      args.struct_map_field.A.value = "ZZZ";
+      args.struct_map_field.B.value = "ZZZ";
+      args.struct_nested_containers_field[0][0].C[0] = "ZZZ";
+      args.struct_nested_containers_field[0][0].C[1] = "ZZZ";
+      args.struct_nested_containers_field2.D[0].DA = "ZZZ";
+      args.struct_nested_containers_field2.D[0].DB = "ZZZ";
 
       assertValues(tObj, assert);
       assert.end();
     },
 
     "nulls are ok": function(assert) {
-      var tObj = new ttypes.Complex({
+      const tObj = new ttypes.Complex({
         struct_field: null,
         struct_list_field: null,
         struct_set_field: null,
@@ -296,7 +298,7 @@
         struct_nested_containers_field: null,
         struct_nested_containers_field2: null
       });
-      var received = deserialize(serialize(tObj), ttypes.Complex);
+      const received = deserialize(serialize(tObj), ttypes.Complex);
       assert.strictEqual(tObj.struct_field, null);
       assert.ok(tObj !== received);
       assert.deepEqual(tObj, received);
@@ -304,11 +306,11 @@
     },
 
     "Can make list with objects": function(assert) {
-      var tObj = new ttypes.ComplexList({
-        "struct_list_field": [new ttypes.Complex({})]
+      const tObj = new ttypes.ComplexList({
+        struct_list_field: [new ttypes.Complex({})]
       });
-      var innerObj = tObj.struct_list_field[0];
-      assert.ok(innerObj instanceof ttypes.Complex)
+      const innerObj = tObj.struct_list_field[0];
+      assert.ok(innerObj instanceof ttypes.Complex);
       assert.strictEqual(innerObj.struct_field, null);
       assert.strictEqual(innerObj.struct_list_field, null);
       assert.strictEqual(innerObj.struct_set_field, null);
@@ -317,17 +319,15 @@
       assert.strictEqual(innerObj.struct_nested_containers_field2, null);
       assert.end();
     }
-
   };
   return cases;
 }
 
-
-function run(name, cases){
+function run(name, cases) {
   Object.keys(cases).forEach(function(caseName) {
-    test(name + ': ' + caseName, cases[caseName]);
+    test(name + ": " + caseName, cases[caseName]);
   });
 }
 
-run('binary', createTestCases(serializeBinary, deserializeBinary));
-run('json', createTestCases(serializeJSON, deserializeJSON));
+run("binary", createTestCases(serializeBinary, deserializeBinary));
+run("json", createTestCases(serializeJSON, deserializeJSON));
diff --git a/lib/nodejs/test/exceptions.js b/lib/nodejs/test/exceptions.js
index 0a75770..ab2798a 100644
--- a/lib/nodejs/test/exceptions.js
+++ b/lib/nodejs/test/exceptions.js
@@ -17,58 +17,130 @@
  * under the License.
  */
 
-'use strict';
-var test = require('tape');
-var thrift = require('../lib/thrift/thrift.js');
-var InputBufferUnderrunError = require('../lib/thrift/input_buffer_underrun_error');
+"use strict";
+const test = require("tape");
+const thrift = require("../lib/thrift/thrift.js");
+const InputBufferUnderrunError = require("../lib/thrift/input_buffer_underrun_error");
 
-test('TApplicationException', function t(assert) {
-  var e = new thrift.TApplicationException(1, 'foo');
-  assert.ok(e instanceof thrift.TApplicationException, 'is instanceof TApplicationException');
-  assert.ok(e instanceof thrift.TException, 'is instanceof TException');
-  assert.ok(e instanceof Error, 'is instanceof Error');
-  assert.equal(typeof e.stack, 'string', 'has stack trace');
-  assert.ok(/^TApplicationException: foo/.test(e.stack), 'Stack trace has correct error name and message');
-  assert.ok(e.stack.indexOf('test/exceptions.js:7:11') !== -1, 'stack trace starts on correct line and column');
-  assert.equal(e.name, 'TApplicationException', 'has function name TApplicationException');
-  assert.equal(e.message, 'foo', 'has error message "foo"');
-  assert.equal(e.type, 1, 'has type 1');
+test("TApplicationException", function t(assert) {
+  const e = new thrift.TApplicationException(1, "foo");
+  assert.ok(
+    e instanceof thrift.TApplicationException,
+    "is instanceof TApplicationException"
+  );
+  assert.ok(e instanceof thrift.TException, "is instanceof TException");
+  assert.ok(e instanceof Error, "is instanceof Error");
+  assert.equal(typeof e.stack, "string", "has stack trace");
+  assert.ok(
+    /^TApplicationException: foo/.test(e.stack),
+    "Stack trace has correct error name and message"
+  );
+  assert.ok(
+    e.stack.indexOf("test/exceptions.js:7:11") !== -1,
+    "stack trace starts on correct line and column"
+  );
+  assert.equal(
+    e.name,
+    "TApplicationException",
+    "has function name TApplicationException"
+  );
+  assert.equal(e.message, "foo", 'has error message "foo"');
+  assert.equal(e.type, 1, "has type 1");
   assert.end();
 });
 
-test('TException', function t(assert) {
-  var e = new thrift.TException('foo');
-  assert.ok(e instanceof thrift.TException, 'is instanceof TException');
-  assert.ok(e instanceof Error, 'is instanceof Error');
-  assert.equal(typeof e.stack, 'string', 'has stack trace');
-  assert.ok(/^TException: foo/.test(e.stack), 'Stack trace has correct error name and message');
-  assert.ok(e.stack.indexOf('test/exceptions.js:21:11') !== -1, 'stack trace starts on correct line and column');
-  assert.equal(e.name, 'TException', 'has function name TException');
-  assert.equal(e.message, 'foo', 'has error message "foo"');
+test("unexpected TApplicationException ", function t(assert) {
+  const e = new thrift.TApplicationException(1, 100);
+  assert.ok(
+    e instanceof thrift.TApplicationException,
+    "is instanceof TApplicationException"
+  );
+  assert.ok(e instanceof thrift.TException, "is instanceof TException");
+  assert.ok(e instanceof Error, "is instanceof Error");
+  assert.equal(typeof e.stack, "string", "has stack trace");
+  assert.ok(
+    /^TApplicationException: 100/.test(e.stack),
+    "Stack trace has correct error name and message"
+  );
+  assert.ok(
+    e.stack.indexOf("test/exceptions.js:7:11") !== -1,
+    "stack trace starts on correct line and column"
+  );
+  assert.equal(
+    e.name,
+    "TApplicationException",
+    "has function name TApplicationException"
+  );
+  assert.equal(e.message, 100, "has error message 100");
+  assert.equal(e.type, 1, "has type 1");
   assert.end();
 });
 
-test('TProtocolException', function t(assert) {
-  var e = new thrift.TProtocolException(1, 'foo');
-  assert.ok(e instanceof thrift.TProtocolException, 'is instanceof TProtocolException');
-  assert.ok(e instanceof Error, 'is instanceof Error');
-  assert.equal(typeof e.stack, 'string', 'has stack trace');
-  assert.ok(/^TProtocolException: foo/.test(e.stack), 'Stack trace has correct error name and message');
-  assert.ok(e.stack.indexOf('test/exceptions.js:33:11') !== -1, 'stack trace starts on correct line and column');
-  assert.equal(e.name, 'TProtocolException', 'has function name TProtocolException');
-  assert.equal(e.message, 'foo', 'has error message "foo"');
-  assert.equal(e.type, 1, 'has type 1');
+test("TException", function t(assert) {
+  const e = new thrift.TException("foo");
+  assert.ok(e instanceof thrift.TException, "is instanceof TException");
+  assert.ok(e instanceof Error, "is instanceof Error");
+  assert.equal(typeof e.stack, "string", "has stack trace");
+  assert.ok(
+    /^TException: foo/.test(e.stack),
+    "Stack trace has correct error name and message"
+  );
+  assert.ok(
+    e.stack.indexOf("test/exceptions.js:21:11") !== -1,
+    "stack trace starts on correct line and column"
+  );
+  assert.equal(e.name, "TException", "has function name TException");
+  assert.equal(e.message, "foo", 'has error message "foo"');
   assert.end();
 });
 
-test('InputBufferUnderrunError', function t(assert) {
-  var e = new InputBufferUnderrunError('foo');
-  assert.ok(e instanceof InputBufferUnderrunError, 'is instanceof InputBufferUnderrunError');
-  assert.ok(e instanceof Error, 'is instanceof Error');
-  assert.equal(typeof e.stack, 'string', 'has stack trace');
-  assert.ok(/^InputBufferUnderrunError: foo/.test(e.stack), 'Stack trace has correct error name and message');
-  assert.ok(e.stack.indexOf('test/exceptions.js:46:11') !== -1, 'stack trace starts on correct line and column');
-  assert.equal(e.name, 'InputBufferUnderrunError', 'has function name InputBufferUnderrunError');
-  assert.equal(e.message, 'foo', 'has error message "foo"');
+test("TProtocolException", function t(assert) {
+  const e = new thrift.TProtocolException(1, "foo");
+  assert.ok(
+    e instanceof thrift.TProtocolException,
+    "is instanceof TProtocolException"
+  );
+  assert.ok(e instanceof Error, "is instanceof Error");
+  assert.equal(typeof e.stack, "string", "has stack trace");
+  assert.ok(
+    /^TProtocolException: foo/.test(e.stack),
+    "Stack trace has correct error name and message"
+  );
+  assert.ok(
+    e.stack.indexOf("test/exceptions.js:33:11") !== -1,
+    "stack trace starts on correct line and column"
+  );
+  assert.equal(
+    e.name,
+    "TProtocolException",
+    "has function name TProtocolException"
+  );
+  assert.equal(e.message, "foo", 'has error message "foo"');
+  assert.equal(e.type, 1, "has type 1");
+  assert.end();
+});
+
+test("InputBufferUnderrunError", function t(assert) {
+  const e = new InputBufferUnderrunError("foo");
+  assert.ok(
+    e instanceof InputBufferUnderrunError,
+    "is instanceof InputBufferUnderrunError"
+  );
+  assert.ok(e instanceof Error, "is instanceof Error");
+  assert.equal(typeof e.stack, "string", "has stack trace");
+  assert.ok(
+    /^InputBufferUnderrunError: foo/.test(e.stack),
+    "Stack trace has correct error name and message"
+  );
+  assert.ok(
+    e.stack.indexOf("test/exceptions.js:46:11") !== -1,
+    "stack trace starts on correct line and column"
+  );
+  assert.equal(
+    e.name,
+    "InputBufferUnderrunError",
+    "has function name InputBufferUnderrunError"
+  );
+  assert.equal(e.message, "foo", 'has error message "foo"');
   assert.end();
 });
diff --git a/lib/nodejs/test/helpers.js b/lib/nodejs/test/helpers.js
index 5f828b3..72d128d 100644
--- a/lib/nodejs/test/helpers.js
+++ b/lib/nodejs/test/helpers.js
@@ -17,16 +17,21 @@
  * under the License.
  */
 
-'use strict';
-var thrift = require('../lib/thrift');
+"use strict";
+const thrift = require("../lib/thrift");
 
 module.exports.transports = {
-  'buffered': thrift.TBufferedTransport,
-  'framed': thrift.TFramedTransport
+  buffered: thrift.TBufferedTransport,
+  framed: thrift.TFramedTransport
 };
 
 module.exports.protocols = {
-  'json': thrift.TJSONProtocol,
-  'binary': thrift.TBinaryProtocol,
-  'compact': thrift.TCompactProtocol
+  json: thrift.TJSONProtocol,
+  binary: thrift.TBinaryProtocol,
+  compact: thrift.TCompactProtocol
 };
+
+module.exports.ecmaMode = process.argv.includes("--es6") ? "es6" : "es5";
+module.exports.genPath = process.argv.includes("--es6")
+  ? "gen-nodejs-es6"
+  : "gen-nodejs";
diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.js
index 8f2e06b..7402094 100644
--- a/lib/nodejs/test/server.js
+++ b/lib/nodejs/test/server.js
@@ -19,88 +19,119 @@
  * under the License.
  */
 
-var fs = require('fs');
-var path = require('path');
-var thrift = require('../lib/thrift');
-var program = require('commander');
-var helpers = require('./helpers');
-
-var ThriftTest = require('./gen-nodejs/ThriftTest');
-var SecondService = require('./gen-nodejs/SecondService');
-var ThriftTestHandler = require('./test_handler').AsyncThriftTestHandler;
-var ThriftTestHandlerPromise = require('./test_handler').SyncThriftTestHandler;
-var ttypes = require('./gen-nodejs/ThriftTest_types');
+const fs = require("fs");
+const path = require("path");
+const thrift = require("../lib/thrift");
+const program = require("commander");
+const helpers = require("./helpers");
 
 program
-  .option('-p, --protocol <protocol>', 'Set thrift protocol (binary|compact|json)', 'binary')
-  .option('-t, --transport <transport>', 'Set thrift transport (buffered|framed|http)', 'buffered')
-  .option('--ssl', 'use ssl transport')
-  .option('--port <port>', 'Set thrift server port', 9090)
-  .option('--promise', 'test with promise style functions')
-  .option('-t, --type <type>', 'Select server type (http|multiplex|tcp|websocket)', 'tcp')
+  .option(
+    "-p, --protocol <protocol>",
+    "Set thrift protocol (binary|compact|json)",
+    "binary"
+  )
+  .option(
+    "-t, --transport <transport>",
+    "Set thrift transport (buffered|framed|http)",
+    "buffered"
+  )
+  .option("--ssl", "use ssl transport")
+  .option("--port <port>", "Set thrift server port", 9090)
+  .option("--domain-socket <path>", "Set thift server unix domain socket")
+  .option(
+    "-t, --type <type>",
+    "Select server type (http|multiplex|tcp|websocket)",
+    "tcp"
+  )
+  .option("--callback", "test with callback style functions")
+  .option("--es6", "Use es6 code")
+  .option("--es5", "Use es5 code")
   .parse(process.argv);
 
-var port = program.port;
-var type = program.type;
-var ssl = program.ssl;
-var promise = program.promise;
+const ThriftTest = require(`./${helpers.genPath}/ThriftTest`);
+const SecondService = require(`./${helpers.genPath}/SecondService`);
+const { ThriftTestHandler } = require("./test_handler");
 
-var handler = program.promise ? ThriftTestHandler : ThriftTestHandlerPromise;
+const port = program.port;
+const domainSocket = program.domainSocket;
+const ssl = program.ssl;
 
-if (program.transport === 'http') {
-  program.transport = 'buffered';
-  type = 'http';
+let type = program.type;
+if (program.transport === "http") {
+  program.transport = "buffered";
+  type = "http";
 }
 
-var options = {
+let options = {
   transport: helpers.transports[program.transport],
   protocol: helpers.protocols[program.protocol]
 };
 
-if (type === 'http' || type ==='websocket') {
-  options.handler = handler;
+if (type === "http" || type === "websocket") {
+  options.handler = ThriftTestHandler;
   options.processor = ThriftTest;
 
   options = {
     services: { "/test": options },
     cors: {
-      '*': true
+      "*": true
     }
-  }
+  };
 }
 
-if (type === 'multiplex') {
-  var SecondServiceHandler = {
+let processor;
+if (type === "multiplex") {
+  const SecondServiceHandler = {
     secondtestString: function(thing, result) {
       console.log('testString("' + thing + '")');
       result(null, 'testString("' + thing + '")');
     }
   };
 
-  var processor = new thrift.MultiplexedProcessor();
+  processor = new thrift.MultiplexedProcessor();
 
-  processor.registerProcessor("ThriftTest",
-    new ThriftTest.Processor(ThriftTestHandler));
+  processor.registerProcessor(
+    "ThriftTest",
+    new ThriftTest.Processor(ThriftTestHandler)
+  );
 
-  processor.registerProcessor("SecondService",
-    new SecondService.Processor(SecondServiceHandler));
-
+  processor.registerProcessor(
+    "SecondService",
+    new SecondService.Processor(SecondServiceHandler)
+  );
 }
 
 if (ssl) {
-  options.tls = {
-    key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
-    cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
-  };
+  if (
+    type === "tcp" ||
+    type === "multiplex" ||
+    type === "http" ||
+    type === "websocket"
+  ) {
+    options.tls = {
+      key: fs.readFileSync(path.resolve(__dirname, "server.key")),
+      cert: fs.readFileSync(path.resolve(__dirname, "server.crt"))
+    };
+  }
 }
 
-var server;
-if (type === 'tcp') {
-  server = thrift.createServer(ThriftTest, handler, options);
-} else if (type === 'multiplex') {
+let server;
+if (type === "tcp") {
+  server = thrift.createServer(ThriftTest, ThriftTestHandler, options);
+} else if (type === "multiplex") {
   server = thrift.createMultiplexServer(processor, options);
-} else if (type === 'http' || type === 'websocket') {
+} else if (type === "http" || type === "websocket") {
   server = thrift.createWebServer(options);
 }
 
-server.listen(port);
+if (domainSocket) {
+  server.listen(domainSocket);
+} else if (
+  type === "tcp" ||
+  type === "multiplex" ||
+  type === "http" ||
+  type === "websocket"
+) {
+  server.listen(port);
+}
diff --git a/lib/nodejs/test/test-cases.js b/lib/nodejs/test/test-cases.js
index bd66dc4..02c566f 100644
--- a/lib/nodejs/test/test-cases.js
+++ b/lib/nodejs/test/test-cases.js
@@ -17,139 +17,156 @@
  * under the License.
  */
 
-'use strict';
+"use strict";
 
-var ttypes = require('./gen-nodejs/ThriftTest_types');
-var Int64 = require('node-int64');
+const helpers = require("./helpers");
+const ttypes = require(`./${helpers.genPath}/ThriftTest_types`);
+const Int64 = require("node-int64");
 
 //all Languages in UTF-8
 /*jshint -W100 */
-var stringTest = module.exports.stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " +
-    "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " +
-    "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " +
-    "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, " +
-    "Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, " +
-    "Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, " +
-    "Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, " +
-    "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " +
-    "Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, " +
-    "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, " +
-    "Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, " +
-    "ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, " +
-    "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " +
-    "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa " +
-    "Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa " +
-    "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" +
-    "Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, " +
-    "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " +
-    "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " +
-    "Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " +
-    "English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, " +
-    "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " +
-    "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " +
-    "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " +
-    "Bân-lâm-gú, 粵語";
+const stringTest = (module.exports.stringTest =
+  "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " +
+  "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " +
+  "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " +
+  "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, " +
+  "Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, " +
+  "Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, " +
+  "Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, " +
+  "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " +
+  "Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, " +
+  "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, " +
+  "Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, " +
+  "ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, " +
+  "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " +
+  "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa " +
+  "Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa " +
+  "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" +
+  "Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, " +
+  "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " +
+  "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " +
+  "Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " +
+  "English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, " +
+  "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " +
+  "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " +
+  "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " +
+  "Bân-lâm-gú, 粵語");
 /*jshint +W100 */
 
-var specialCharacters = module.exports.specialCharacters = 'quote: \" backslash:' +
-    ' forwardslash-escaped: \/ ' +
-    ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
-    ' now-all-of-them-together: "\\\/\b\n\r\t' +
-    ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><' +
-    ' char-to-test-json-parsing: ]] \"]] \\" }}}{ [[[ ';
+const specialCharacters = (module.exports.specialCharacters =
+  'quote: " backslash:' +
+  " forwardslash-escaped: / " +
+  " backspace: \b formfeed: \f newline: \n return: \r tab: " +
+  ' now-all-of-them-together: "\\/\b\n\r\t' +
+  " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" +
+  ' char-to-test-json-parsing: ]] "]] \\" }}}{ [[[ ');
 
-var mapTestInput = module.exports.mapTestInput = {
-  "a":"123", "a b":"with spaces ", "same":"same", "0":"numeric key",
-  "longValue":stringTest, stringTest:"long key"
-};
+const mapTestInput = (module.exports.mapTestInput = {
+  a: "123",
+  "a b": "with spaces ",
+  same: "same",
+  "0": "numeric key",
+  longValue: stringTest,
+  stringTest: "long key"
+});
 
-var simple = [
-  ['testVoid', undefined],
-  ['testString', 'Test'],
-  ['testString', ''],
-  ['testString', stringTest],
-  ['testString', specialCharacters],
-  ['testBool', true],
-  ['testBool', false],
-  ['testByte', 1],
-  ['testByte', 0],
-  ['testByte', -1],
-  ['testByte', -127],
-  ['testI32', -1],
-  ['testDouble', -5.2098523],
-  ['testDouble', 7.012052175215044],
-  ['testEnum', ttypes.Numberz.ONE],
-  ['testI64', 5],
-  ['testI64', -5],
-  ['testI64', 734359738368],
-  ['testI64', -734359738368],
-  ['testI64', new Int64(new Buffer([0, 0x20, 0, 0, 0, 0, 0, 1]))],  // 2^53+1
-  ['testI64', new Int64(
-      new Buffer([0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]))],  // -2^53-1
-  ['testTypedef', 69]
-]
+const simple = [
+  ["testVoid", undefined],
+  ["testString", "Test"],
+  ["testString", ""],
+  ["testString", stringTest],
+  ["testString", specialCharacters],
+  ["testBool", true],
+  ["testBool", false],
+  ["testByte", 1],
+  ["testByte", 0],
+  ["testByte", -1],
+  ["testByte", -127],
+  ["testI32", -1],
+  ["testDouble", -5.2098523],
+  ["testDouble", 7.012052175215044],
+  ["testEnum", ttypes.Numberz.ONE],
+  ["testI64", 5],
+  ["testI64", -5],
+  ["testI64", 734359738368],
+  ["testI64", -734359738368],
+  ["testI64", new Int64(new Buffer([0, 0x20, 0, 0, 0, 0, 0, 1]))], // 2^53+1
+  [
+    "testI64",
+    new Int64(new Buffer([0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]))
+  ], // -2^53-1
+  ["testTypedef", 69]
+];
 
-var mapout = {};
-for (var i = 0; i < 5; ++i) {
-  mapout[i] = i-10;
+const mapout = {};
+for (let i = 0; i < 5; ++i) {
+  mapout[i] = i - 10;
 }
 
-var deep = [
-  ['testList', [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]],
+const deep = [
+  [
+    "testList",
+    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
+  ]
 ];
 
-var deepUnordered = [
-  ['testMap', mapout],
-  ['testSet', [1,2,3]],
-  ['testStringMap', mapTestInput]
+const deepUnordered = [
+  ["testMap", mapout],
+  ["testSet", [1, 2, 3]],
+  ["testStringMap", mapTestInput]
 ];
 
-var out = new ttypes.Xtruct({
-  string_thing: 'Zero',
+const out = new ttypes.Xtruct({
+  string_thing: "Zero",
   byte_thing: 1,
   i32_thing: -3,
   i64_thing: 1000000
 });
 
-var out2 = new ttypes.Xtruct2();
+const out2 = new ttypes.Xtruct2();
 out2.byte_thing = 1;
 out2.struct_thing = out;
 out2.i32_thing = 5;
 
-var crazy = new ttypes.Insanity({
-  "userMap":{ "5":5, "8":8 },
-  "xtructs":[new ttypes.Xtruct({
-      "string_thing":"Goodbye4",
-      "byte_thing":4,
-      "i32_thing":4,
-      "i64_thing":4
-    }), new ttypes.Xtruct({
-      "string_thing":"Hello2",
-      "byte_thing":2,
-      "i32_thing":2,
-      "i64_thing":2
-    })]
+const crazy = new ttypes.Insanity({
+  userMap: { "5": 5, "8": 8 },
+  xtructs: [
+    new ttypes.Xtruct({
+      string_thing: "Goodbye4",
+      byte_thing: 4,
+      i32_thing: 4,
+      i64_thing: 4
+    }),
+    new ttypes.Xtruct({
+      string_thing: "Hello2",
+      byte_thing: 2,
+      i32_thing: 2,
+      i64_thing: 2
+    })
+  ]
 });
 
-var crazy2 = new ttypes.Insanity({
-  "userMap":{ "5":5, "8":8 },
-  "xtructs":[{
-      "string_thing":"Goodbye4",
-      "byte_thing":4,
-      "i32_thing":4,
-      "i64_thing":4
-    }, {
-      "string_thing":"Hello2",
-      "byte_thing":2,
-      "i32_thing":2,
-      "i64_thing":2
-    }]
+const crazy2 = new ttypes.Insanity({
+  userMap: { "5": 5, "8": 8 },
+  xtructs: [
+    {
+      string_thing: "Goodbye4",
+      byte_thing: 4,
+      i32_thing: 4,
+      i64_thing: 4
+    },
+    {
+      string_thing: "Hello2",
+      byte_thing: 2,
+      i32_thing: 2,
+      i64_thing: 2
+    }
+  ]
 });
 
-
-var insanity = {
-  "1":{ "2": crazy, "3": crazy },
-  "2":{ "6":{ "userMap":{}, "xtructs":[] } }
+const insanity = {
+  "1": { "2": crazy, "3": crazy },
+  "2": { "6": { userMap: {}, xtructs: [] } }
 };
 
 module.exports.simple = simple;
diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh
index aae451a..24f1f2e 100755
--- a/lib/nodejs/test/testAll.sh
+++ b/lib/nodejs/test/testAll.sh
@@ -24,7 +24,6 @@
 DIR="$( cd "$( dirname "$0" )" && pwd )"
 
 ISTANBUL="$DIR/../../../node_modules/istanbul/lib/cli.js"
-RUNBROWSER="$DIR/../../../node_modules/run-browser/bin/cli.js"
 
 REPORT_PREFIX="${DIR}/../coverage/report"
 
@@ -34,38 +33,27 @@
 
 testServer()
 {
-  echo "   Testing $1 Client/Server with protocol $2 and transport $3 $4";
+  echo "  [ECMA $1] Testing $2 Client/Server with protocol $3 and transport $4 $5";
   RET=0
   if [ -n "${COVER}" ]; then
-    ${ISTANBUL} cover ${DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $1 -p $2 -t $3 $4 &
+    ${ISTANBUL} cover ${DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $2 -p $3 -t $4 $5 &
     COUNT=$((COUNT+1))
   else
-    node ${DIR}/server.js --type $1 -p $2 -t $3 $4 &
+    node ${DIR}/server.js --${1} --type $2 -p $3 -t $4 $5 &
   fi
   SERVERPID=$!
   sleep 0.1
   if [ -n "${COVER}" ]; then
-    ${ISTANBUL} cover ${DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} -- --type $1 -p $2 -t $3 $4 || RET=1
+    ${ISTANBUL} cover ${DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} -- --${1} --type $2 -p $3 -t $4 $5 || RET=1
     COUNT=$((COUNT+1))
   else
-    node ${DIR}/client.js --type $1 -p $2 -t $3 $4 || RET=1
+    node ${DIR}/client.js --${1} --type $2 -p $3 -t $4 $5 || RET=1
   fi
   kill -2 $SERVERPID || RET=1
   wait $SERVERPID
   return $RET
 }
 
-testBrowser()
-{
-  echo "   Testing browser client with http server with json protocol and buffered transport";
-  RET=0
-  node ${DIR}/server.js --type http -p json -t buffered &
-  SERVERPID=$!
-  sleep 1
-  ${RUNBROWSER} ${DIR}/browser_client.js --phantom || RET=1
-  kill -2 $SERVERPID || RET=1
-  return $RET
-}
 
 TESTOK=0
 
@@ -73,6 +61,9 @@
 
 ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/ThriftTest.thrift
 ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/JsDeepConstructorTest.thrift
+mkdir ${DIR}/gen-nodejs-es6
+${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/ThriftTest.thrift
+${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/JsDeepConstructorTest.thrift
 
 #unit tests
 
@@ -83,21 +74,20 @@
 
 for type in tcp multiplex websocket http
 do
-
   for protocol in compact binary json
   do
-
     for transport in buffered framed
     do
-      testServer $type $protocol $transport || TESTOK=1
-      testServer $type $protocol $transport --ssl || TESTOK=1
-      testServer $type $protocol $transport --promise || TESTOK=1
+      for ecma_version in es5 es6
+      do
+        testServer $ecma_version $type $protocol $transport || TESTOK=1
+        testServer $ecma_version $type $protocol $transport --ssl || TESTOK=1
+        testServer $ecma_version $type $protocol $transport --callback || TESTOK=1
+      done
     done
   done
 done
 
-# XHR only until phantomjs 2 is released.
-# testBrowser
 
 if [ -n "${COVER}" ]; then
   ${ISTANBUL} report --dir "${DIR}/../coverage" --include "${DIR}/../coverage/report*/coverage.json" lcov cobertura html
diff --git a/lib/nodejs/test/test_driver.js b/lib/nodejs/test/test_driver.js
index 03ec513..7c9a919 100644
--- a/lib/nodejs/test/test_driver.js
+++ b/lib/nodejs/test/test_driver.js
@@ -17,247 +17,279 @@
  * under the License.
  */
 
- // This is the Node.js test driver for the standard Apache Thrift
- // test service. The driver invokes every function defined in the
- // Thrift Test service with a representative range of parameters.
- //
- // The ThriftTestDriver function requires a client object
- // connected to a server hosting the Thrift Test service and
- // supports an optional callback function which is called with
- // a status message when the test is complete.
+// This is the Node.js test driver for the standard Apache Thrift
+// test service. The driver invokes every function defined in the
+// Thrift Test service with a representative range of parameters.
+//
+// The ThriftTestDriver function requires a client object
+// connected to a server hosting the Thrift Test service and
+// supports an optional callback function which is called with
+// a status message when the test is complete.
 
-var test = require('tape');
-//var assert = require('assert');
-var ttypes = require('./gen-nodejs/ThriftTest_types');
-var TException = require('thrift').Thrift.TException;
-var Int64 = require('node-int64');
-var testCases = require('./test-cases');
+const test = require("tape");
+
+const helpers = require("./helpers");
+const ttypes = require(`./${helpers.genPath}/ThriftTest_types`);
+const TException = require("thrift").Thrift.TException;
+const Int64 = require("node-int64");
+const testCases = require("./test-cases");
 
 exports.ThriftTestDriver = function(client, callback) {
+  test(
+    "NodeJS Style Callback Client Tests",
+    { skip: helpers.ecmaMode === "es6" },
+    function(assert) {
+      const checkRecursively = makeRecursiveCheck(assert);
 
-  test('NodeJS Style Callback Client Tests', function(assert) {
-
-    var checkRecursively = makeRecursiveCheck(assert);
-
-    function makeAsserter(assertionFn) {
-      return function(c) {
-        var fnName = c[0];
-        var expected = c[1];
-        client[fnName](expected, function(err, actual) {
-          assert.error(err, fnName + ': no callback error');
-          assertionFn(actual, expected, fnName);
-        })
-      };
-    }
-
-    testCases.simple.forEach(makeAsserter(function(a, e, m){
-      if (a instanceof Int64) {
-        var e64 = e instanceof Int64 ? e : new Int64(e);
-        assert.deepEqual(a.buffer, e64.buffer, m);
-      } else {
-        assert.equal(a, e, m);
+      function makeAsserter(assertionFn) {
+        return function(c) {
+          const fnName = c[0];
+          const expected = c[1];
+          client[fnName](expected, function(err, actual) {
+            assert.error(err, fnName + ": no callback error");
+            assertionFn(actual, expected, fnName);
+          });
+        };
       }
-    }));
-    testCases.deep.forEach(makeAsserter(assert.deepEqual));
-    testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
 
-    var arr = [];
-    for (var i = 0; i < 256; ++i) {
-      arr[i] = 255 - i;
-    }
-    var buf = new Buffer(arr);
-    client.testBinary(buf, function(err, response) {
-      assert.error(err, 'testBinary: no callback error');
-      assert.equal(response.length, 256, 'testBinary');
-      assert.deepEqual(response, buf, 'testBinary(Buffer)');
-    });
-    var buf = new Buffer(arr);
-    client.testBinary(buf.toString('binary'), function(err, response) {
-      assert.error(err, 'testBinary: no callback error');
-      assert.equal(response.length, 256, 'testBinary');
-      assert.deepEqual(response, buf, 'testBinary(string)');
-    });
+      testCases.simple.forEach(
+        makeAsserter(function(a, e, m) {
+          if (a instanceof Int64) {
+            const e64 = e instanceof Int64 ? e : new Int64(e);
+            assert.deepEqual(a.buffer, e64.buffer, m);
+          } else {
+            assert.equal(a, e, m);
+          }
+        })
+      );
+      testCases.deep.forEach(makeAsserter(assert.deepEqual));
+      testCases.deepUnordered.forEach(
+        makeAsserter(makeUnorderedDeepEqual(assert))
+      );
 
-    client.testMapMap(42, function(err, response) {
-      var expected = {
-        "4": {"1":1, "2":2, "3":3, "4":4},
-        "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
-      };
-      assert.error(err, 'testMapMap: no callback error');
-      assert.deepEqual(expected, response, 'testMapMap');
-    });
-
-    client.testStruct(testCases.out, function(err, response) {
-      assert.error(err, 'testStruct: no callback error');
-      checkRecursively(testCases.out, response, 'testStruct');
-    });
-
-    client.testNest(testCases.out2, function(err, response) {
-      assert.error(err, 'testNest: no callback error');
-      checkRecursively(testCases.out2, response, 'testNest');
-    });
-
-    client.testInsanity(testCases.crazy, function(err, response) {
-      assert.error(err, 'testInsanity: no callback error');
-      checkRecursively(testCases.insanity, response, 'testInsanity');
-    });
-
-    client.testInsanity(testCases.crazy2, function(err, response) {
-      assert.error(err, 'testInsanity2: no callback error');
-      checkRecursively(testCases.insanity, response, 'testInsanity2');
-    });
-
-    client.testException('TException', function(err, response) {
-      assert.ok(err instanceof TException, 'testException: correct error type');
-      assert.ok(!response, 'testException: no response');
-    });
-
-    client.testException('Xception', function(err, response) {
-      assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
-      assert.ok(!response, 'testException: no response');
-      assert.equal(err.errorCode, 1001, 'testException: correct error code');
-      assert.equal('Xception', err.message, 'testException: correct error message');
-    });
-
-    client.testException('no Exception', function(err, response) {
-      assert.error(err, 'testException: no callback error');
-      assert.ok(!response, 'testException: no response');
-    });
-
-    client.testOneway(0, function(err, response) {
-      assert.fail('testOneway should not answer');
-    });
-
-    checkOffByOne(function(done) {
-      client.testI32(-1, function(err, response) {
-        assert.error(err, 'checkOffByOne: no callback error');
-        assert.equal(-1, response);
-        assert.end();
-        done();
+      const arr = [];
+      for (let i = 0; i < 256; ++i) {
+        arr[i] = 255 - i;
+      }
+      let buf = new Buffer(arr);
+      client.testBinary(buf, function(err, response) {
+        assert.error(err, "testBinary: no callback error");
+        assert.equal(response.length, 256, "testBinary");
+        assert.deepEqual(response, buf, "testBinary(Buffer)");
       });
-    }, callback);
+      buf = new Buffer(arr);
+      client.testBinary(buf.toString("binary"), function(err, response) {
+        assert.error(err, "testBinary: no callback error");
+        assert.equal(response.length, 256, "testBinary");
+        assert.deepEqual(response, buf, "testBinary(string)");
+      });
 
-  });
+      client.testMapMap(42, function(err, response) {
+        const expected = {
+          "4": { "1": 1, "2": 2, "3": 3, "4": 4 },
+          "-4": { "-4": -4, "-3": -3, "-2": -2, "-1": -1 }
+        };
+        assert.error(err, "testMapMap: no callback error");
+        assert.deepEqual(expected, response, "testMapMap");
+      });
+
+      client.testStruct(testCases.out, function(err, response) {
+        assert.error(err, "testStruct: no callback error");
+        checkRecursively(testCases.out, response, "testStruct");
+      });
+
+      client.testNest(testCases.out2, function(err, response) {
+        assert.error(err, "testNest: no callback error");
+        checkRecursively(testCases.out2, response, "testNest");
+      });
+
+      client.testInsanity(testCases.crazy, function(err, response) {
+        assert.error(err, "testInsanity: no callback error");
+        checkRecursively(testCases.insanity, response, "testInsanity");
+      });
+
+      client.testInsanity(testCases.crazy2, function(err, response) {
+        assert.error(err, "testInsanity2: no callback error");
+        checkRecursively(testCases.insanity, response, "testInsanity2");
+      });
+
+      client.testException("TException", function(err, response) {
+        assert.ok(
+          err instanceof TException,
+          "testException: correct error type"
+        );
+        assert.ok(!response, "testException: no response");
+      });
+
+      client.testException("Xception", function(err, response) {
+        assert.ok(
+          err instanceof ttypes.Xception,
+          "testException: correct error type"
+        );
+        assert.ok(!response, "testException: no response");
+        assert.equal(err.errorCode, 1001, "testException: correct error code");
+        assert.equal(
+          "Xception",
+          err.message,
+          "testException: correct error message"
+        );
+      });
+
+      client.testException("no Exception", function(err, response) {
+        assert.error(err, "testException: no callback error");
+        assert.ok(!response, "testException: no response");
+      });
+
+      client.testOneway(0, function(err, response) {
+        assert.error(err, "testOneway: no callback error");
+        assert.strictEqual(response, undefined, "testOneway: void response");
+      });
+
+      checkOffByOne(function(done) {
+        client.testI32(-1, function(err, response) {
+          assert.error(err, "checkOffByOne: no callback error");
+          assert.equal(-1, response);
+          assert.end();
+          done();
+        });
+      }, callback);
+    }
+  );
+
+  // ES6 does not support callback style
+  if (helpers.ecmaMode === "es6") {
+    checkOffByOne(done => done(), callback);
+  }
 };
 
 exports.ThriftTestDriverPromise = function(client, callback) {
-
-  test('Q Promise Client Tests', function(assert) {
-
-    var checkRecursively = makeRecursiveCheck(assert);
-
-    function fail(msg) {
-      return function() {
-        assert.fail(msg);
-      }
-    }
+  test("Promise Client Tests", function(assert) {
+    const checkRecursively = makeRecursiveCheck(assert);
 
     function makeAsserter(assertionFn) {
       return function(c) {
-        var fnName = c[0];
-        var expected = c[1];
+        const fnName = c[0];
+        const expected = c[1];
         client[fnName](expected)
           .then(function(actual) {
             assertionFn(actual, expected, fnName);
           })
-          .fail(fail('fnName'));
+          .catch(() => assert.fail("fnName"));
       };
     }
 
-    testCases.simple.forEach(makeAsserter(function(a, e, m){
-      if (a instanceof Int64) {
-        var e64 = e instanceof Int64 ? e : new Int64(e);
-        assert.deepEqual(a.buffer, e64.buffer, m);
-      } else {
-        assert.equal(a, e, m);
-      }
-    }));
+    testCases.simple.forEach(
+      makeAsserter(function(a, e, m) {
+        if (a instanceof Int64) {
+          const e64 = e instanceof Int64 ? e : new Int64(e);
+          assert.deepEqual(a.buffer, e64.buffer, m);
+        } else {
+          assert.equal(a, e, m);
+        }
+      })
+    );
     testCases.deep.forEach(makeAsserter(assert.deepEqual));
-    testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
+    testCases.deepUnordered.forEach(
+      makeAsserter(makeUnorderedDeepEqual(assert))
+    );
 
-    client.testStruct(testCases.out)
+    client
+      .testStruct(testCases.out)
       .then(function(response) {
-        checkRecursively(testCases.out, response, 'testStruct');
+        checkRecursively(testCases.out, response, "testStruct");
       })
-      .fail(fail('testStruct'));
+      .catch(() => assert.fail("testStruct"));
 
-    client.testNest(testCases.out2)
+    client
+      .testNest(testCases.out2)
       .then(function(response) {
-        checkRecursively(testCases.out2, response, 'testNest');
+        checkRecursively(testCases.out2, response, "testNest");
       })
-      .fail(fail('testNest'));
+      .catch(() => assert.fail("testNest"));
 
-    client.testInsanity(testCases.crazy)
+    client
+      .testInsanity(testCases.crazy)
       .then(function(response) {
-        checkRecursively(testCases.insanity, response, 'testInsanity');
+        checkRecursively(testCases.insanity, response, "testInsanity");
       })
-      .fail(fail('testInsanity'));
+      .catch(() => assert.fail("testInsanity"));
 
-    client.testInsanity(testCases.crazy2)
+    client
+      .testInsanity(testCases.crazy2)
       .then(function(response) {
-        checkRecursively(testCases.insanity, response, 'testInsanity2');
+        checkRecursively(testCases.insanity, response, "testInsanity2");
       })
-      .fail(fail('testInsanity2'));
+      .catch(() => assert.fail("testInsanity2"));
 
-    client.testException('TException')
-      .then(function(response) {
-        fail('testException: TException');
+    client
+      .testException("TException")
+      .then(function() {
+        assert.fail("testException: TException");
       })
-      .fail(function(err) {
+      .catch(function(err) {
         assert.ok(err instanceof TException);
       });
 
-    client.testException('Xception')
-      .then(function(response) {
-        fail('testException: Xception');
+    client
+      .testException("Xception")
+      .then(function() {
+        assert.fail("testException: Xception");
       })
-      .fail(function(err) {
+      .catch(function(err) {
         assert.ok(err instanceof ttypes.Xception);
         assert.equal(err.errorCode, 1001);
-        assert.equal('Xception', err.message);
+        assert.equal("Xception", err.message);
       });
 
-    client.testException('no Exception')
+    client
+      .testException("no Exception")
       .then(function(response) {
         assert.equal(undefined, response); //void
       })
-      .fail(fail('testException'));
+      .catch(() => assert.fail("testException"));
 
-    client.testOneway(0, fail('testOneway: should not answer'));
+    client
+      .testOneway(0)
+      .then(function(response) {
+        assert.strictEqual(response, undefined, "testOneway: void response");
+      })
+      .catch(() => assert.fail("testOneway: should not reject"));
 
     checkOffByOne(function(done) {
-      client.testI32(-1)
+      client
+        .testI32(-1)
         .then(function(response) {
-            assert.equal(-1, response);
-            assert.end();
-            done();
+          assert.equal(-1, response);
+          assert.end();
+          done();
         })
-        .fail(fail('checkOffByOne'));
+        .catch(() => assert.fail("checkOffByOne"));
     }, callback);
   });
 };
 
-
 // Helper Functions
 // =========================================================
 
 function makeRecursiveCheck(assert) {
-
-  return function (map1, map2, msg) {
-    var equal = true;
-
-    var equal = checkRecursively(map1, map2);
+  return function(map1, map2, msg) {
+    const equal = checkRecursively(map1, map2);
 
     assert.ok(equal, msg);
 
     // deepEqual doesn't work with fields using node-int64
     function checkRecursively(map1, map2) {
-      if (typeof map1 !== 'function' && typeof map2 !== 'function') {
-        if (!map1 || typeof map1 !== 'object') {
+      if (typeof map1 !== "function" && typeof map2 !== "function") {
+        if (!map1 || typeof map1 !== "object") {
           //Handle int64 types (which use node-int64 in Node.js JavaScript)
-          if ((typeof map1 === "number") && (typeof map2 === "object") &&
-              (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
-            var n = new Int64(map2.buffer);
+          if (
+            typeof map1 === "number" &&
+            typeof map2 === "object" &&
+            map2.buffer &&
+            map2.buffer instanceof Buffer &&
+            map2.buffer.length === 8
+          ) {
+            const n = new Int64(map2.buffer);
             return map1 === n.toNumber();
           } else {
             return map1 == map2;
@@ -269,15 +301,14 @@
         }
       }
     }
-  }
+  };
 }
 
 function checkOffByOne(done, callback) {
-
-  var retry_limit = 30;
-  var retry_interval = 100;
-  var test_complete = false;
-  var retrys = 0;
+  const retry_limit = 30;
+  const retry_interval = 100;
+  let test_complete = false;
+  let retrys = 0;
 
   /**
    * redo a simple test after the oneway to make sure we aren't "off by one" --
@@ -294,14 +325,17 @@
 
   //We wait up to retry_limit * retry_interval for the test suite to complete
   function TestForCompletion() {
-    if(test_complete && callback) {
+    if (test_complete && callback) {
       callback("Server successfully tested!");
     } else {
       if (++retrys < retry_limit) {
         setTimeout(TestForCompletion, retry_interval);
       } else if (callback) {
-        callback("Server test failed to complete after " +
-                 (retry_limit * retry_interval / 1000) + " seconds");
+        callback(
+          "Server test failed to complete after " +
+            (retry_limit * retry_interval) / 1000 +
+            " seconds"
+        );
       }
     }
   }
@@ -312,15 +346,15 @@
 function makeUnorderedDeepEqual(assert) {
   return function(actual, expected, name) {
     assert.equal(actual.length, expected.length, name);
-    for (var k in actual) {
-      var found = false;
-      for (var k2 in expected) {
+    for (const k in actual) {
+      let found = false;
+      for (const k2 in expected) {
         if (actual[k] === expected[k2]) {
           found = true;
         }
       }
       if (!found) {
-        assert.fail('Unexpected value ' + actual[k] + ' with key ' + k);
+        assert.fail("Unexpected value " + actual[k] + " with key " + k);
       }
     }
   };
diff --git a/lib/nodejs/test/test_handler.js b/lib/nodejs/test/test_handler.js
index 5c89f7a..317a7c8 100644
--- a/lib/nodejs/test/test_handler.js
+++ b/lib/nodejs/test/test_handler.js
@@ -19,18 +19,17 @@
 
 //This is the server side Node test handler for the standard
 //  Apache Thrift test service.
+const helpers = require("./helpers");
+const ttypes = require(`./${helpers.genPath}/ThriftTest_types`);
+const TException = require("thrift").Thrift.TException;
 
-var ttypes = require('./gen-nodejs/ThriftTest_types');
-var TException = require('thrift').Thrift.TException;
-
-function makeSyncHandler(label) {
+function makeSyncHandler() {
   return function(thing) {
-    //console.log(label + '(\'' + thing + '\')');
     return thing;
-  }
+  };
 }
 
-var syncHandlers = {
+const syncHandlers = {
   testVoid: testVoid,
   testMapMap: testMapMap,
   testInsanity: testInsanity,
@@ -44,10 +43,10 @@
   return function(thing, result) {
     thing = syncHandlers[label](thing);
     result(null, thing);
-  }
+  };
 }
 
-var asyncHandlers = {
+const asyncHandlers = {
   testVoid: testVoidAsync,
   testMulti: testMultiAsync,
   testException: testExceptionAsync,
@@ -55,22 +54,22 @@
   testOneway: testOnewayAsync
 };
 
-var identityHandlers = [
-  'testString',
-  'testBool',
-  'testByte',
-  'testI32',
-  'testI64',
-  'testDouble',
-  'testBinary',
-  'testStruct',
-  'testNest',
-  'testMap',
-  'testStringMap',
-  'testSet',
-  'testList',
-  'testEnum',
-  'testTypedef'
+const identityHandlers = [
+  "testString",
+  "testBool",
+  "testByte",
+  "testI32",
+  "testI64",
+  "testDouble",
+  "testBinary",
+  "testStruct",
+  "testNest",
+  "testMap",
+  "testStringMap",
+  "testSet",
+  "testList",
+  "testEnum",
+  "testTypedef"
 ];
 
 function testVoid() {
@@ -81,13 +80,11 @@
   result(testVoid());
 }
 
-function testMapMap(hello) {
-  //console.log('testMapMap(' + hello + ')');
-
-  var mapmap = [];
-  var pos = [];
-  var neg = [];
-  for (var i = 1; i < 5; i++) {
+function testMapMap() {
+  const mapmap = [];
+  const pos = [];
+  const neg = [];
+  for (let i = 1; i < 5; i++) {
     pos[i] = i;
     neg[-i] = -i;
   }
@@ -102,16 +99,16 @@
   //console.log(argument);
   //console.log(')');
 
-  var first_map = [];
-  var second_map = [];
+  const first_map = [];
+  const second_map = [];
 
   first_map[ttypes.Numberz.TWO] = argument;
   first_map[ttypes.Numberz.THREE] = argument;
 
-  var looney = new ttypes.Insanity();
+  const looney = new ttypes.Insanity();
   second_map[ttypes.Numberz.SIX] = looney;
 
-  var insane = [];
+  const insane = [];
   insane[1] = first_map;
   insane[2] = second_map;
 
@@ -120,11 +117,11 @@
   return insane;
 }
 
-function testMulti(arg0, arg1, arg2, arg3, arg4, arg5) {
+function testMulti(arg0, arg1, arg2) {
   //console.log('testMulti()');
 
-  var hello = new ttypes.Xtruct();
-  hello.string_thing = 'Hello2';
+  const hello = new ttypes.Xtruct();
+  hello.string_thing = "Hello2";
   hello.byte_thing = arg0;
   hello.i32_thing = arg1;
   hello.i64_thing = arg2;
@@ -132,18 +129,18 @@
 }
 
 function testMultiAsync(arg0, arg1, arg2, arg3, arg4, arg5, result) {
-  var hello = testMulti(arg0, arg1, arg2, arg3, arg4, arg5);
+  const hello = testMulti(arg0, arg1, arg2, arg3, arg4, arg5);
   result(null, hello);
 }
 
 function testException(arg) {
   //console.log('testException('+arg+')');
-  if (arg === 'Xception') {
-    var x = new ttypes.Xception();
+  if (arg === "Xception") {
+    const x = new ttypes.Xception();
     x.errorCode = 1001;
     x.message = arg;
     throw x;
-  } else if (arg === 'TException') {
+  } else if (arg === "TException") {
     throw new TException(arg);
   } else {
     return;
@@ -152,12 +149,12 @@
 
 function testExceptionAsync(arg, result) {
   //console.log('testException('+arg+')');
-  if (arg === 'Xception') {
-    var x = new ttypes.Xception();
+  if (arg === "Xception") {
+    const x = new ttypes.Xception();
     x.errorCode = 1001;
     x.message = arg;
     result(x);
-  } else if (arg === 'TException') {
+  } else if (arg === "TException") {
     result(new TException(arg));
   } else {
     result(null);
@@ -166,49 +163,48 @@
 
 function testMultiException(arg0, arg1) {
   //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')');
-  if (arg0 === ('Xception')) {
-    var x = new ttypes.Xception();
+  if (arg0 === "Xception") {
+    const x = new ttypes.Xception();
     x.errorCode = 1001;
-    x.message = 'This is an Xception';
+    x.message = "This is an Xception";
     throw x;
-  } else if (arg0 === ('Xception2')) {
-    var x2 = new ttypes.Xception2();
+  } else if (arg0 === "Xception2") {
+    const x2 = new ttypes.Xception2();
     x2.errorCode = 2002;
     x2.struct_thing = new ttypes.Xtruct();
-    x2.struct_thing.string_thing = 'This is an Xception2';
+    x2.struct_thing.string_thing = "This is an Xception2";
     throw x2;
   }
 
-  var res = new ttypes.Xtruct();
+  const res = new ttypes.Xtruct();
   res.string_thing = arg1;
   return res;
 }
 
 function testMultiExceptionAsync(arg0, arg1, result) {
   //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')');
-  if (arg0 === ('Xception')) {
-    var x = new ttypes.Xception();
+  if (arg0 === "Xception") {
+    const x = new ttypes.Xception();
     x.errorCode = 1001;
-    x.message = 'This is an Xception';
+    x.message = "This is an Xception";
     result(x);
-  } else if (arg0 === ('Xception2')) {
-    var x2 = new ttypes.Xception2();
+  } else if (arg0 === "Xception2") {
+    const x2 = new ttypes.Xception2();
     x2.errorCode = 2002;
     x2.struct_thing = new ttypes.Xtruct();
-    x2.struct_thing.string_thing = 'This is an Xception2';
+    x2.struct_thing.string_thing = "This is an Xception2";
     result(x2);
   } else {
-    var res = new ttypes.Xtruct();
+    const res = new ttypes.Xtruct();
     res.string_thing = arg1;
     result(null, res);
   }
 }
 
-function testOneway(sleepFor) {
-  //console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!');
-}
+//console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!');
+function testOneway() {}
 
-function testOnewayAsync(sleepFor, result) {
+function testOnewayAsync(sleepFor) {
   testOneway(sleepFor);
 }
 
@@ -217,11 +213,8 @@
   asyncHandlers[label] = makeAsyncHandler(label);
 });
 
-['testMapMap', 'testInsanity'].forEach(function(label) {
+["testMapMap", "testInsanity"].forEach(function(label) {
   asyncHandlers[label] = makeAsyncHandler(label);
 });
 
 exports.ThriftTestHandler = asyncHandlers;
-
-exports.AsyncThriftTestHandler = asyncHandlers;
-exports.SyncThriftTestHandler = asyncHandlers;
diff --git a/lib/nodets/.gitignore b/lib/nodets/.gitignore
new file mode 100644
index 0000000..c7aba89
--- /dev/null
+++ b/lib/nodets/.gitignore
@@ -0,0 +1 @@
+test-compiled/
diff --git a/lib/nodets/Makefile.am b/lib/nodets/Makefile.am
new file mode 100755
index 0000000..ea640cf
--- /dev/null
+++ b/lib/nodets/Makefile.am
@@ -0,0 +1,45 @@
+# 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.
+
+# We call npm twice to work around npm issues
+
+stubs: $(top_srcdir)/test/ThriftTest.thrift
+	mkdir -p test-compiled
+	$(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/ThriftTest.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/ThriftTest.thrift
+
+ts-compile: stubs
+	mkdir -p test-compiled
+	../../node_modules/typescript/bin/tsc --outDir test-compiled/ --project test/tsconfig.json
+
+deps: $(top_srcdir)/package.json
+	$(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/
+
+all-local: deps ts-compile
+
+precross: deps stubs ts-compile
+
+check: deps ts-compile
+	cd $(top_srcdir) && $(NPM) run test-ts && cd lib/nodets
+
+clean-local:
+	$(RM) -r test/gen-nodejs
+	$(RM) -r $(top_srcdir)/node_modules
+	$(RM) -r test-compiled
+
+EXTRA_DIST = \
+	test \
+	coding_standards.md
diff --git a/lib/nodets/coding_standards.md b/lib/nodets/coding_standards.md
new file mode 100644
index 0000000..fa0390b
--- /dev/null
+++ b/lib/nodets/coding_standards.md
@@ -0,0 +1 @@
+Please follow [General Coding Standards](/doc/coding_standards.md)
diff --git a/lib/nodets/test/client.ts b/lib/nodets/test/client.ts
new file mode 100644
index 0000000..4fa3c28
--- /dev/null
+++ b/lib/nodets/test/client.ts
@@ -0,0 +1,63 @@
+/*
+ * 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 assert = require("assert");
+import thrift = require("thrift");
+import Thrift = thrift.Thrift;
+import ThriftTest = require("./gen-nodejs/ThriftTest");
+import test_driver = require("./test_driver");
+import ThriftTestDriver = test_driver.ThriftTestDriver;
+import ThriftTestDriverPromise = test_driver.ThriftTestDriverPromise;
+
+// var program = require("commander");
+import * as program from "commander";
+
+program
+  .option("--port <port>", "Set thrift server port number to connect", 9090)
+  .option("--promise", "test with promise style functions")
+  .option("--protocol", "Set thrift protocol (binary) [protocol]")
+  .parse(process.argv);
+
+var port: number = program.port;
+var promise = program.promise;
+
+var options = {
+  transport: Thrift.TBufferedTransport,
+  protocol: Thrift.TBinaryProtocol
+};
+
+var testDriver = promise ? ThriftTestDriverPromise : ThriftTestDriver;
+
+var connection = thrift.createConnection("localhost", port, options);
+
+connection.on("error", function(err: string) {
+    assert(false, err);
+});
+
+var client = thrift.createClient(ThriftTest.Client, connection);
+runTests();
+
+function runTests() {
+  testDriver(client, function (status: string) {
+    console.log(status);
+    process.exit(0);
+  });
+}
+
+exports.expressoTest = function() {};
diff --git a/lib/nodets/test/runClient.sh b/lib/nodets/test/runClient.sh
new file mode 100755
index 0000000..8d5e9a3
--- /dev/null
+++ b/lib/nodets/test/runClient.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+DIR="$( cd "$( dirname "$0" )" && pwd )"
+
+mkdir -p $DIR/../test-compiled
+
+COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)"
+export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}"
+
+compile()
+{
+  #generating thrift code
+  ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+  ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+}
+compile
+
+node ${COMPILEDDIR}/client.js $*
diff --git a/lib/nodets/test/runServer.sh b/lib/nodets/test/runServer.sh
new file mode 100755
index 0000000..4eee927
--- /dev/null
+++ b/lib/nodets/test/runServer.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+DIR="$( cd "$( dirname "$0" )" && pwd )"
+
+mkdir -p $DIR/../test-compiled
+
+COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)"
+export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}"
+
+compile()
+{
+  #generating thrift code
+  ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+  ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+}
+compile
+
+node ${COMPILEDDIR}/server.js $*
+
+
diff --git a/lib/nodets/test/server.ts b/lib/nodets/test/server.ts
new file mode 100644
index 0000000..2da53ae
--- /dev/null
+++ b/lib/nodets/test/server.ts
@@ -0,0 +1,26 @@
+import thrift = require("thrift");
+var program = require('commander');
+import ThriftTest = require('./gen-nodejs/ThriftTest');
+import test_handler = require('./test_handler');
+
+
+program
+  .option('--port <port>', 'Set thrift server port', 9090)
+  .option('--promise', 'test with promise style functions')
+  .option('--protocol', '"Set thrift protocol (binary) [protocol]"')
+  .parse(process.argv);
+
+var port: number = program.port;
+
+var options: thrift.ServerOptions = {
+  transport: thrift.TBufferedTransport,
+  protocol: thrift.TBinaryProtocol
+};
+
+var server: thrift.Server;
+if (program.promise) {
+  server = thrift.createServer(ThriftTest.Processor, new test_handler.AsyncThriftTestHandler(), options);
+} else {
+  server = thrift.createServer(ThriftTest.Processor, new test_handler.SyncThriftTestHandler(), options);
+}
+server.listen(port);
diff --git a/lib/nodets/test/test-cases.ts b/lib/nodets/test/test-cases.ts
new file mode 100644
index 0000000..ca740ec
--- /dev/null
+++ b/lib/nodets/test/test-cases.ts
@@ -0,0 +1,113 @@
+'use strict';
+
+import ttypes = require('./gen-nodejs/ThriftTest_types');
+
+//all Languages in UTF-8
+/*jshint -W100 */
+export var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " +
+    "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " +
+    "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " +
+    "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, " +
+    "Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, " +
+    "Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, " +
+    "Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, " +
+    "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " +
+    "Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, " +
+    "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, " +
+    "Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, " +
+    "ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, " +
+    "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " +
+    "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa " +
+    "Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa " +
+    "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" +
+    "Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, " +
+    "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " +
+    "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " +
+    "Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " +
+    "English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, " +
+    "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " +
+    "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " +
+    "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " +
+    "Bân-lâm-gú, 粵語";
+/*jshint +W100 */
+
+export var specialCharacters = 'quote: \" backslash:' +
+    ' forwardslash-escaped: \/ ' +
+    ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
+    ' now-all-of-them-together: "\\\/\b\n\r\t' +
+    ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><' +
+    ' char-to-test-json-parsing: ]] \"]] \\" }}}{ [[[ ';
+
+export var mapTestInput = {
+  "a":"123", "a b":"with spaces ", "same":"same", "0":"numeric key",
+  "longValue":stringTest, stringTest:"long key"
+};
+
+export var simple = [
+  ['testVoid', undefined],
+  ['testString', 'Test'],
+  ['testString', ''],
+  ['testString', stringTest],
+  ['testString', specialCharacters],
+  ['testByte', 1],
+  ['testByte', 0],
+  ['testByte', -1],
+  ['testByte', -127],
+  ['testI32', -1],
+  ['testDouble', -5.2098523],
+  ['testDouble', 7.012052175215044],
+  ['testEnum', ttypes.Numberz.ONE]
+];
+
+export var simpleLoose = [
+  ['testI64', 5],
+  ['testI64', -5],
+  ['testI64', 734359738368],
+  ['testI64', -34359738368],
+  ['testI64', -734359738368],
+  ['testTypedef', 69]
+]
+
+var mapout: {[key: number]: number; } = {};
+for (var i = 0; i < 5; ++i) {
+  mapout[i] = i-10;
+}
+
+export var deep = [
+  ['testMap', mapout],
+  ['testSet', [1,2,3]],
+  ['testList', [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]],
+  ['testStringMap', mapTestInput]
+];
+
+export var out = new ttypes.Xtruct({
+  string_thing: 'Zero',
+  byte_thing: 1,
+  i32_thing: -3,
+  i64_thing: 1000000
+});
+
+export var out2 = new ttypes.Xtruct2();
+out2.byte_thing = 1;
+out2.struct_thing = out;
+out2.i32_thing = 5;
+
+export var crazy = new ttypes.Insanity({
+  "userMap":{ "5":5, "8":8 },
+  "xtructs":[new ttypes.Xtruct({
+      "string_thing":"Goodbye4",
+      "byte_thing":4,
+      "i32_thing":4,
+      "i64_thing":4
+    }), new ttypes.Xtruct({
+      "string_thing":"Hello2",
+      "byte_thing":2,
+      "i32_thing":2,
+      "i64_thing":2
+    })]
+});
+
+export var insanity: any = {
+  "1":{ "2": crazy, "3": crazy },
+  "2":{ "6":{ "userMap":{}, "xtructs":[] } }
+};
diff --git a/lib/nodets/test/testAll.sh b/lib/nodets/test/testAll.sh
new file mode 100755
index 0000000..a7c00bf
--- /dev/null
+++ b/lib/nodets/test/testAll.sh
@@ -0,0 +1,38 @@
+#! /bin/sh
+
+DIR="$( cd "$( dirname "$0" )" && pwd )"
+
+mkdir -p $DIR/../test-compiled
+
+COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)"
+export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}"
+
+compile()
+{
+  #generating thrift code
+  ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+  ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift
+
+  tsc --outDir $COMPILEDDIR --project $DIR/tsconfig.json
+}
+compile
+
+testServer()
+{
+  echo "start server $1"
+  RET=0
+  node ${COMPILEDDIR}/server.js $1 &
+  SERVERPID=$!
+  sleep 1
+  echo "start client $1"
+  node ${COMPILEDDIR}/client.js $1 || RET=1
+  kill -2 $SERVERPID || RET=1
+  return $RET
+}
+
+#integration tests
+
+testServer || TESTOK=1
+testServer --promise || TESTOK=1
+
+exit $TESTOK
diff --git a/lib/nodets/test/test_driver.ts b/lib/nodets/test/test_driver.ts
new file mode 100644
index 0000000..2c41526
--- /dev/null
+++ b/lib/nodets/test/test_driver.ts
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ */
+
+ // This is the Node.js test driver for the standard Apache Thrift
+ // test service. The driver invokes every function defined in the
+ // Thrift Test service with a representative range of parameters.
+ //
+ // The ThriftTestDriver function requires a client object
+ // connected to a server hosting the Thrift Test service and
+ // supports an optional callback function which is called with
+ // a status message when the test is complete.
+
+import test = require("tape");
+import ttypes = require("./gen-nodejs/ThriftTest_types");
+import ThriftTest = require("./gen-nodejs/ThriftTest");
+import thrift = require("thrift");
+import Q = thrift.Q;
+import TException = thrift.Thrift.TException;
+var Int64 = require("node-int64");
+import testCases = require("./test-cases");
+
+export function ThriftTestDriver(client: ThriftTest.Client, callback: (status: string) => void) {
+
+  test("NodeJS Style Callback Client Tests", function(assert) {
+
+    var checkRecursively = makeRecursiveCheck(assert);
+
+    function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) {
+      return function(c: (string | any)[]) {
+        var fnName = c[0];
+        var expected = c[1];
+        (<any>client)[fnName](expected, function(err: any, actual: any) {
+          assert.error(err, fnName + ": no callback error");
+          assertionFn(actual, expected, fnName);
+        })
+      };
+    }
+
+    testCases.simple.forEach(makeAsserter(assert.equal));
+    testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
+      assert.ok(a == e, m);
+    }));
+    testCases.deep.forEach(makeAsserter(assert.deepEqual));
+
+    client.testMapMap(42, function(err, response) {
+      var expected: typeof response = {
+        "4": {"1":1, "2":2, "3":3, "4":4},
+        "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
+      };
+      assert.error(err, 'testMapMap: no callback error');
+      assert.deepEqual(expected, response, "testMapMap");
+    });
+
+    client.testStruct(testCases.out, function(err, response) {
+      assert.error(err, "testStruct: no callback error");
+      checkRecursively(testCases.out, response, "testStruct");
+    });
+
+    client.testNest(testCases.out2, function(err, response) {
+      assert.error(err, "testNest: no callback error");
+      checkRecursively(testCases.out2, response, "testNest");
+    });
+
+    client.testInsanity(testCases.crazy, function(err, response) {
+      assert.error(err, "testInsanity: no callback error");
+      checkRecursively(testCases.insanity, response, "testInsanity");
+    });
+
+    client.testException("TException", function(err, response) {
+      assert.ok(err instanceof TException, 'testException: correct error type');
+      assert.ok(!Boolean(response), 'testException: no response');
+    });
+
+    client.testException("Xception", function(err, response) {
+      assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
+      assert.ok(!Boolean(response), 'testException: no response');
+      assert.equal(err.errorCode, 1001, 'testException: correct error code');
+      assert.equal('Xception', err.message, 'testException: correct error message');
+    });
+
+    client.testException("no Exception", function(err, response) {
+      assert.error(err, 'testException: no callback error');
+      assert.ok(!Boolean(response), 'testException: no response');
+    });
+
+    client.testOneway(0, function(err, response) {
+      assert.error(err, 'testOneway: no callback error');
+      assert.strictEqual(response, undefined, 'testOneway: void response');
+    });
+
+    checkOffByOne(function(done) {
+      client.testI32(-1, function(err, response) {
+        assert.error(err, "checkOffByOne: no callback error");
+        assert.equal(-1, response);
+        assert.end();
+        done();
+      });
+    }, callback);
+
+  });
+};
+
+export function ThriftTestDriverPromise(client: ThriftTest.Client, callback: (status: string) => void) {
+
+  test("Q Promise Client Tests", function(assert) {
+
+    var checkRecursively = makeRecursiveCheck(assert);
+
+    function fail(msg: string) {
+      return function(error, response) {
+        if (error !== null) {
+          assert.fail(msg);
+        }
+      }
+    }
+
+    function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) {
+      return function(c: (string | any)[]) {
+        var fnName = c[0];
+        var expected = c[1];
+        (<any>client)[fnName](expected)
+          .then(function(actual: any) {
+            assertionFn(actual, expected, fnName);
+          })
+          .fail(fail("fnName"));
+      };
+    }
+
+    testCases.simple.forEach(makeAsserter(assert.equal));
+    testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
+      assert.ok(a == e, m);
+    }));
+    testCases.deep.forEach(makeAsserter(assert.deepEqual));
+
+    Q.resolve(client.testStruct(testCases.out))
+      .then(function(response) {
+        checkRecursively(testCases.out, response, "testStruct");
+      })
+      .fail(fail("testStruct"));
+
+    Q.resolve(client.testNest(testCases.out2))
+      .then(function(response) {
+        checkRecursively(testCases.out2, response, "testNest");
+      })
+      .fail(fail("testNest"));
+
+    Q.resolve(client.testInsanity(testCases.crazy))
+      .then(function(response) {
+        checkRecursively(testCases.insanity, response, "testInsanity");
+      })
+      .fail(fail("testInsanity"));
+
+    Q.resolve(client.testException("TException"))
+      .then(function(response) {
+        fail("testException: TException");
+      })
+      .fail(function(err) {
+        assert.ok(err instanceof TException);
+      });
+
+    Q.resolve(client.testException("Xception"))
+      .then(function(response) {
+        fail("testException: Xception");
+      })
+      .fail(function(err) {
+        assert.ok(err instanceof ttypes.Xception);
+        assert.equal(err.errorCode, 1001);
+        assert.equal("Xception", err.message);
+      });
+
+    Q.resolve(client.testException("no Exception"))
+      .then(function(response) {
+        assert.equal(undefined, response); //void
+      })
+      .fail(fail("testException"));
+
+    client.testOneway(0, fail("testOneway: should not answer"));
+
+    checkOffByOne(function(done) {
+      Q.resolve(client.testI32(-1))
+        .then(function(response) {
+            assert.equal(-1, response);
+            assert.end();
+            done();
+        })
+        .fail(fail("checkOffByOne"));
+    }, callback);
+  });
+};
+
+
+// Helper Functions
+// =========================================================
+
+function makeRecursiveCheck(assert: test.Test) {
+
+  return function (map1: any, map2: any, msg: string) {
+    var equal = true;
+
+    var equal = checkRecursively(map1, map2);
+
+    assert.ok(equal, msg);
+
+    // deepEqual doesn't work with fields using node-int64
+    function checkRecursively(map1: any, map2: any) : boolean {
+      if (!(typeof map1 !== "function" && typeof map2 !== "function")) {
+        return false;
+      }
+      if (!map1 || typeof map1 !== "object") {
+        //Handle int64 types (which use node-int64 in Node.js JavaScript)
+        if ((typeof map1 === "number") && (typeof map2 === "object") &&
+            (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
+          var n = new Int64(map2.buffer);
+          return map1 === n.toNumber();
+        } else {
+          return map1 == map2;
+        }
+      } else {
+        return Object.keys(map1).every(function(key) {
+          return checkRecursively(map1[key], map2[key]);
+        });
+      }
+    }
+  }
+}
+
+function checkOffByOne(done: (callback: () => void) => void, callback: (message: string) => void) {
+
+  var retry_limit = 30;
+  var retry_interval = 100;
+  var test_complete = false;
+  var retrys = 0;
+
+  /**
+   * redo a simple test after the oneway to make sure we aren't "off by one" --
+   * if the server treated oneway void like normal void, this next test will
+   * fail since it will get the void confirmation rather than the correct
+   * result. In this circumstance, the client will throw the exception:
+   *
+   * Because this is the last test against the server, when it completes
+   * the entire suite is complete by definition (the tests run serially).
+   */
+  done(function() {
+    test_complete = true;
+  });
+
+  //We wait up to retry_limit * retry_interval for the test suite to complete
+  function TestForCompletion() {
+    if(test_complete && callback) {
+      callback("Server successfully tested!");
+    } else {
+      if (++retrys < retry_limit) {
+        setTimeout(TestForCompletion, retry_interval);
+      } else if (callback) {
+        callback("Server test failed to complete after " +
+                 (retry_limit * retry_interval / 1000) + " seconds");
+      }
+    }
+  }
+
+  setTimeout(TestForCompletion, retry_interval);
+}
diff --git a/lib/nodets/test/test_handler.ts b/lib/nodets/test/test_handler.ts
new file mode 100644
index 0000000..1bc855a
--- /dev/null
+++ b/lib/nodets/test/test_handler.ts
@@ -0,0 +1,299 @@
+/*
+ * 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.
+ */
+
+//This is the server side Node test handler for the standard
+//  Apache Thrift test service.
+
+import ttypes = require("./gen-nodejs/ThriftTest_types");
+import thrift = require("thrift");
+import Thrift = thrift.Thrift;
+import Q = require("q");
+
+
+export class SyncThriftTestHandler {
+  testVoid(): Q.IPromise<void> {
+    //console.log('testVoid()');
+    return Q.resolve<void>(undefined);
+  }
+  testMapMap(hello: number) {
+    //console.log('testMapMap(' + hello + ')');
+
+    var mapmap: {[key: number]: {[key: number]: number; }} = [];
+    var pos: {[key: number]: number; } = [];
+    var neg: {[key: number]: number; } = [];
+    for (var i = 1; i < 5; i++) {
+      pos[i] = i;
+      neg[-i] = -i;
+    }
+    mapmap[4] = pos;
+    mapmap[-4] = neg;
+
+    return Q.resolve(mapmap);
+  }
+  testInsanity(argument: ttypes.Insanity): Q.IPromise<{ [k: number]: any; }> {
+    const first_map: { [k: number]: any; } = [];
+    const second_map: { [k: number]: any; } = [];
+  
+    first_map[ttypes.Numberz.TWO] = argument;
+    first_map[ttypes.Numberz.THREE] = argument;
+  
+    const looney = new ttypes.Insanity();
+    second_map[ttypes.Numberz.SIX] = looney;
+  
+    const insane: { [k: number]: any; } = [];
+    insane[1] = first_map;
+    insane[2] = second_map;
+
+    return Q.resolve(insane);
+  }
+  testMulti(arg0: any, arg1: number, arg2: number, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number) {
+    var hello = new ttypes.Xtruct();
+    hello.string_thing = 'Hello2';
+    hello.byte_thing = arg0;
+    hello.i32_thing = arg1;
+    hello.i64_thing = arg2;
+    return Q.resolve(hello);
+  }
+  testException(arg: string): Q.IPromise<void> {
+    if (arg === 'Xception') {
+      var x = new ttypes.Xception();
+      x.errorCode = 1001;
+      x.message = arg;
+      throw x;
+    } else if (arg === 'TException') {
+      throw new Thrift.TException(arg);
+    } else {
+      return Q.resolve();
+    }
+  }
+  testMultiException(arg0: string, arg1: string) {
+    if (arg0 === ('Xception')) {
+      var x = new ttypes.Xception();
+      x.errorCode = 1001;
+      x.message = 'This is an Xception';
+      throw x;
+    } else if (arg0 === ('Xception2')) {
+      var x2 = new ttypes.Xception2();
+      x2.errorCode = 2002;
+      x2.struct_thing = new ttypes.Xtruct();
+      x2.struct_thing.string_thing = 'This is an Xception2';
+      throw x2;
+    }
+
+    var res = new ttypes.Xtruct();
+    res.string_thing = arg1;
+    return Q.resolve(res);
+  }
+  testOneway(sleepFor: number) {
+  }
+
+  testString(thing: string) {
+    return Q.resolve(thing);
+  }
+  testBool(thing: boolean) {
+    return Q.resolve(thing);
+  }
+  testByte(thing: number) {
+    return Q.resolve(thing);
+  }
+  testI32(thing: number) {
+    return Q.resolve(thing);
+  }
+  testI64(thing: number) {
+    return Q.resolve(thing);
+  }
+  testDouble(thing: number) {
+    return Q.resolve(thing);
+  }
+  testBinary(thing: Buffer) {
+    return Q.resolve(thing);
+  }
+  testStruct(thing: ttypes.Xtruct) {
+    return Q.resolve(thing);
+  }
+  testNest(thing: ttypes.Xtruct2) {
+    return Q.resolve(thing);
+  }
+  testMap(thing: { [k: number]: number; }) {
+    return Q.resolve(thing);
+  }
+  testStringMap(thing: { [k: string]: string; }) {
+    return Q.resolve(thing);
+  }
+  testSet(thing: number[]) {
+    return Q.resolve(thing);
+  }
+  testList(thing: number[]) {
+    return Q.resolve(thing);
+  }
+  testEnum(thing: ttypes.Numberz) {
+    return Q.resolve(thing);
+  }
+  testTypedef(thing: number) {
+    return Q.resolve(thing);
+  }
+}
+
+export class AsyncThriftTestHandler {
+  private syncHandler: SyncThriftTestHandler;
+  constructor() {
+    this.syncHandler = new SyncThriftTestHandler();
+  }
+
+  testVoid(callback: (result: void) => void): Q.IPromise<void> {
+    callback(undefined);
+    return Q.resolve();
+  }
+  testMapMap(hello: number,
+    callback: (err: any, result: { [k: number]: { [k: number]: number; }; }) => void):
+     Q.IPromise<{ [k: number]: { [k: number]: number; }; }> {
+
+    var mapmap: {[key: number]: {[key: number]: number; }} = [];
+    var pos: {[key: number]: number; } = [];
+    var neg: {[key: number]: number; } = [];
+    for (var i = 1; i < 5; i++) {
+      pos[i] = i;
+      neg[-i] = -i;
+    }
+    mapmap[4] = pos;
+    mapmap[-4] = neg;
+
+    callback(null, mapmap);
+    return Q.resolve();
+  }
+  testInsanity(argument: ttypes.Insanity, callback?: (err: any, result: { [k: number]: any; }) => void): Q.IPromise<{ [k: number]: any; }> {
+    const first_map: { [k: number]: any; } = [];
+    const second_map: { [k: number]: any; } = [];
+  
+    first_map[ttypes.Numberz.TWO] = argument;
+    first_map[ttypes.Numberz.THREE] = argument;
+  
+    const looney = new ttypes.Insanity();
+    second_map[ttypes.Numberz.SIX] = looney;
+  
+    const insane: { [k: number]: any; } = [];
+    insane[1] = first_map;
+    insane[2] = second_map;
+
+    if (callback !== undefined){
+      callback(null, insane);
+    }
+    return Q.resolve();
+  }
+  testMulti(arg0: any, arg1: number, arg2: number, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number, result: Function): Q.IPromise<ttypes.Xtruct> {
+    var hello = this.syncHandler.testMulti(arg0, arg1, arg2, arg3, arg4, arg5);
+    hello.then(hello => result(null, hello));
+    return Q.resolve();
+  }
+  testException(arg: string, result: (err: any) => void): Q.IPromise<void> {
+    if (arg === 'Xception') {
+      var x = new ttypes.Xception();
+      x.errorCode = 1001;
+      x.message = arg;
+      result(x);
+    } else if (arg === 'TException') {
+      result(new Thrift.TException(arg));
+    } else {
+      result(null);
+    }
+    return Q.resolve();
+  }
+  testMultiException(arg0: string, arg1: string, result: (err: any, res?: ttypes.Xtruct) => void): Q.IPromise<ttypes.Xtruct> {
+    if (arg0 === ('Xception')) {
+      var x = new ttypes.Xception();
+      x.errorCode = 1001;
+      x.message = 'This is an Xception';
+      result(x);
+    } else if (arg0 === ('Xception2')) {
+      var x2 = new ttypes.Xception2();
+      x2.errorCode = 2002;
+      x2.struct_thing = new ttypes.Xtruct();
+      x2.struct_thing.string_thing = 'This is an Xception2';
+      result(x2);
+    } else {
+      var res = new ttypes.Xtruct();
+      res.string_thing = arg1;
+      result(null, res);
+    }
+    return Q.resolve();
+  }
+  testOneway(sleepFor: number, result: Function) {
+    this.syncHandler.testOneway(sleepFor);
+  }
+  testString(thing: string, callback: (err: any, result: string) => void): Q.IPromise<string> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testByte(thing: number, callback: (err: any, result: number) => void): Q.IPromise<number> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testBool(thing: boolean, callback: (err: any, result: boolean) => void ): Q.IPromise<boolean> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testI32(thing: number, callback: (err: any, result: number) => void): Q.IPromise<number>  {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testI64(thing: number, callback: (err: any, result: number) => void): Q.IPromise<number>  {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testDouble(thing: number, callback: (err: any, result: number) => void): Q.IPromise<number>  {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testBinary(thing: Buffer, callback: (err: any, result: Buffer) => void): Q.IPromise<Buffer> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testStruct(thing: ttypes.Xtruct, callback: (err: any, result: ttypes.Xtruct) => void): Q.IPromise<ttypes.Xtruct> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testNest(thing: ttypes.Xtruct2, callback: (err: any, result: ttypes.Xtruct2) => void): Q.IPromise<ttypes.Xtruct2> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testMap(thing: { [k: number]: number; }, callback: (err: any, result: { [k: number]: number; }) => void): Q.IPromise<{ [k: number]: number; }> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testStringMap(thing: { [k: string]: string; }, callback: (err: any, result: { [k: string]: string; }) => void): Q.IPromise<{ [k: string]: string; }> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testSet(thing: number[], callback: (err: any, result: number[]) => void): Q.IPromise<number[]> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testList(thing: number[], callback: (err: any, result: number[]) => void): Q.IPromise<number[]> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testEnum(thing: ttypes.Numberz, callback: (err: any, result: ttypes.Numberz) => void): Q.IPromise<ttypes.Numberz> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+  testTypedef(thing: number, callback: (err: any, result: number) => void): Q.IPromise<number> {
+    callback(null, thing);
+    return Q.resolve();
+  }
+}
diff --git a/lib/nodets/test/tsconfig.json b/lib/nodets/test/tsconfig.json
new file mode 100644
index 0000000..029d06d
--- /dev/null
+++ b/lib/nodets/test/tsconfig.json
@@ -0,0 +1,22 @@
+{
+    "compilerOptions": {
+        "allowJs": false,
+        "alwaysStrict": true,
+        "baseUrl": ".",
+        "declaration": true,
+        "emitDecoratorMetadata": true,
+        "experimentalDecorators": true,
+        "module": "commonjs",
+        "moduleResolution": "node",
+        "noImplicitThis": true,
+        "noUnusedLocals": true,
+        "preserveConstEnums": true,
+        "removeComments": true,
+        "strictFunctionTypes": true,
+        "strictNullChecks": true,
+        "target": "es6",
+        "paths": {
+            "thrift": ["../../nodejs/lib/thrift"]
+        }
+    }
+}
diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis
index 19033e6..5ad90df 100644
--- a/lib/ocaml/_oasis
+++ b/lib/ocaml/_oasis
@@ -1,5 +1,5 @@
 Name: libthrift-ocaml
-Version: 0.11.0
+Version: 1.0.0
 OASISFormat: 0.3
 Synopsis: OCaml bindings for the Apache Thrift RPC system
 Authors: Apache Thrift Developers <dev@thrift.apache.org>
diff --git a/lib/perl/MANIFEST.SKIP b/lib/perl/MANIFEST.SKIP
new file mode 100644
index 0000000..7963b42
--- /dev/null
+++ b/lib/perl/MANIFEST.SKIP
@@ -0,0 +1,13 @@
+blib/.*$
+build-cpan-dist.sh
+FixupDist.pl
+MANIFEST.bak
+MANIFEST.SKIP
+MYMETA.json
+Makefile
+Makefile.am
+Makefile.in
+pm_to_blib
+test/Makefile.am
+test/Makefile.in
+tools/FixupDist.pl
diff --git a/lib/perl/Makefile.PL b/lib/perl/Makefile.PL
index ee7a436..bdeaad2 100644
--- a/lib/perl/Makefile.PL
+++ b/lib/perl/Makefile.PL
@@ -17,7 +17,12 @@
 # under the License.
 #
 
+use 5.10.0;
+use strict;
+use warnings;
+
 use ExtUtils::MakeMaker;
+
 WriteMakefile( ABSTRACT => 'Apache Thrift is a software framework for scalable cross-language services development.',
                AUTHOR => 'Apache Thrift <dev@thrift.apache.org>',
                LICENSE => 'apache_2_0',
diff --git a/lib/perl/build-cpan-dist.sh b/lib/perl/build-cpan-dist.sh
index 1765e6d..ae22e7e 100755
--- a/lib/perl/build-cpan-dist.sh
+++ b/lib/perl/build-cpan-dist.sh
@@ -1,9 +1,53 @@
 #!/bin/bash
 #
 # This script is intended to be used after tagging the repository and updating
-# the version files for a release.  It will create a CPAN archive.
+# the version files for a release.  It will create a CPAN archive.  Run this
+# from inside a docker image like ubuntu-xenial.
+#
+
+set -e
+
+rm -f MANIFEST
+rm -rf Thrift-*
+
+# setup cpan without a prompt
+echo | cpan
+cpan install HTTP::Date
+cpan install CPAN
+cpan install CPAN::Meta ExtUtils::MakeMaker JSON::PP
 
 perl Makefile.PL
-make
+rm MYMETA.yml
 make manifest
 make dist
+
+#
+# We unpack the archive so we can add version metadata for CPAN
+# so that it properly indexes Thrift and remove unnecessary files.
+#
+
+echo '-----------------------------------------------------------'
+set -x
+
+DISTFILE=$(ls Thrift*.gz)
+NEWFILE=${DISTFILE/t-v/t-}
+if [[ "$DISTFILE" != "$NEWFILE" ]]; then
+    mv $DISTFILE $NEWFILE
+    DISTFILE="$NEWFILE"
+fi
+tar xzf $DISTFILE
+rm $DISTFILE
+DISTDIR=$(ls -d Thrift*)
+# cpan doesn't like "Thrift-v0.nn.0 as a directory name
+# needs to be Thrift-0.nn.0
+NEWDIR=${DISTDIR/t-v/t-}
+if [[ "$DISTDIR" != "$NEWDIR" ]]; then
+    mv $DISTDIR $NEWDIR
+    DISTDIR="$NEWDIR"
+fi
+cd $DISTDIR
+cp -p ../Makefile.PL .
+perl ../tools/FixupDist.pl
+cd ..
+tar cvzf $DISTFILE $DISTDIR
+rm -r $DISTDIR
diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm
index cb62353..ab40930 100644
--- a/lib/perl/lib/Thrift.pm
+++ b/lib/perl/lib/Thrift.pm
@@ -31,6 +31,6 @@
 #
 
 package Thrift;
-use version 0.77; our $VERSION = version->declare("v0.11.0");
+use version 0.77; our $VERSION = version->declare("v1.0.0");
 
 1;
diff --git a/lib/perl/lib/Thrift/BinaryProtocol.pm b/lib/perl/lib/Thrift/BinaryProtocol.pm
index 61937e4..d62509a 100644
--- a/lib/perl/lib/Thrift/BinaryProtocol.pm
+++ b/lib/perl/lib/Thrift/BinaryProtocol.pm
@@ -39,7 +39,7 @@
 
 use constant VERSION_MASK   => 0xffff0000;
 use constant VERSION_1      => 0x80010000;
-use constant IS_BIG_ENDIAN  => unpack("h*", pack("s", 1)) =~ /01/;
+use constant IS_BIG_ENDIAN  => unpack('h*', pack('s', 1)) =~ m/01/;
 
 sub new
 {
@@ -67,7 +67,8 @@
     return 0;
 }
 
-sub writeStructBegin{
+sub writeStructBegin
+{
     my $self = shift;
     my $name = shift;
     return 0;
@@ -253,7 +254,7 @@
     my $result = $self->readI32(\$version);
     if (($version & VERSION_MASK) > 0) {
       if (($version & VERSION_MASK) != VERSION_1) {
-        die new Thrift::TProtocolException('Missing version identifier',
+        die Thrift::TProtocolException->new('Missing version identifier',
                                            Thrift::TProtocolException::BAD_VERSION);
       }
       $$type = $version & 0x000000ff;
@@ -261,7 +262,8 @@
           $result +
           $self->readString($name) +
           $self->readI32($seqid);
-    } else { # old client support code
+    }
+    else { # old client support code
       return
         $result +
         $self->readStringBody($name, $version) + # version here holds the size of the string
@@ -427,7 +429,7 @@
 
     my ($hi,$lo)=unpack('NN',$data);
 
-    my $vec = new Bit::Vector(64);
+    my $vec = Bit::Vector->new(64);
 
     $vec->Chunk_Store(32,32,$hi);
     $vec->Chunk_Store(32,0,$lo);
@@ -467,7 +469,8 @@
 
     if ($len) {
       $$value = $self->{trans}->readAll($len);
-    } else {
+    }
+    else {
       $$value = '';
     }
 
@@ -482,7 +485,8 @@
 
     if ($len) {
       $$value = $self->{trans}->readAll($len);
-    } else {
+    }
+    else {
       $$value = '';
     }
 
@@ -508,7 +512,7 @@
     my $self  = shift;
     my $trans = shift;
 
-    return new Thrift::BinaryProtocol($trans);
+    return Thrift::BinaryProtocol->new($trans);
 }
 
 1;
diff --git a/lib/perl/lib/Thrift/Exception.pm b/lib/perl/lib/Thrift/Exception.pm
index 5f0d8fb..e404068 100644
--- a/lib/perl/lib/Thrift/Exception.pm
+++ b/lib/perl/lib/Thrift/Exception.pm
@@ -29,11 +29,10 @@
 
 use overload '""' => sub {
     return
-          ref( $_[0] )
-        . " error: "
-        . ( $_[0]->{message} || 'empty message' )
-        . " (code "
-        . ( defined $_[0]->{code} ? $_[0]->{code} : 'undefined' ) . ")";
+        sprintf '%s error: %s (code %s)',
+          ref( $_[0] ),
+          ( $_[0]->{message} || 'empty message' ),
+          ( defined $_[0]->{code} ? $_[0]->{code} : 'undefined' );
     };
 
 sub new {
@@ -91,7 +90,8 @@
 
               if ($ftype == Thrift::TType::STRING) {
                   $xfer += $input->readString(\$self->{message});
-              } else {
+              }
+              else {
                   $xfer += $input->skip($ftype);
               }
 
@@ -101,7 +101,8 @@
           /2/ && do{
               if ($ftype == Thrift::TType::I32) {
                   $xfer += $input->readI32(\$self->{code});
-              } else {
+              }
+              else {
                   $xfer += $input->skip($ftype);
               }
               last;
diff --git a/lib/perl/lib/Thrift/FramedTransport.pm b/lib/perl/lib/Thrift/FramedTransport.pm
index ee842e6..ba89ba3 100644
--- a/lib/perl/lib/Thrift/FramedTransport.pm
+++ b/lib/perl/lib/Thrift/FramedTransport.pm
@@ -70,7 +70,7 @@
     my $self = shift;
 
     if (defined $self->{transport}) {
-      $self->{transport}->close();
+        $self->{transport}->close();
     }
 }
 
diff --git a/lib/perl/lib/Thrift/HttpClient.pm b/lib/perl/lib/Thrift/HttpClient.pm
index 6e6a631..40ec9ce 100644
--- a/lib/perl/lib/Thrift/HttpClient.pm
+++ b/lib/perl/lib/Thrift/HttpClient.pm
@@ -61,7 +61,7 @@
 
 sub setRecvTimeout
 {
-    warn "setRecvTimeout is deprecated - use setTimeout instead";
+    warn 'setRecvTimeout is deprecated - use setTimeout instead';
     # note: recvTimeout was never used so we do not need to do anything here
 }
 
@@ -70,7 +70,7 @@
     my $self    = shift;
     my $timeout = shift;
 
-    warn "setSendTimeout is deprecated - use setTimeout instead";
+    warn 'setSendTimeout is deprecated - use setTimeout instead';
 
     $self->setTimeout($timeout);
 }
@@ -102,8 +102,8 @@
 {
     my $self = shift;
     if (defined($self->{io})) {
-      close($self->{io});
-      $self->{io} = undef;
+        close($self->{io});
+        $self->{io} = undef;
     }
 }
 
@@ -121,7 +121,7 @@
     my $buf = $self->read($len);
 
     if (!defined($buf)) {
-      die new Thrift::TTransportException("TSocket: Could not read $len bytes from input buffer",
+        die Thrift::TTransportException->new("TSocket: Could not read $len bytes from input buffer",
                                           Thrift::TTransportException::END_OF_FILE);
     }
     return $buf;
@@ -140,17 +140,18 @@
     my $in = $self->{in};
 
     if (!defined($in)) {
-      die new Thrift::TTransportException("Response buffer is empty, no request.",
+        die Thrift::TTransportException->new('Response buffer is empty, no request.',
                                           Thrift::TTransportException::END_OF_FILE);
     }
     eval {
-      my $ret = sysread($in, $buf, $len);
-      if (! defined($ret)) {
-        die new Thrift::TTransportException("No more data available.",
+        my $ret = sysread($in, $buf, $len);
+        if (! defined($ret)) {
+            die Thrift::TTransportException->new('No more data available.',
                                             Thrift::TTransportException::TIMED_OUT);
-      }
-    }; if($@){
-      die new Thrift::TTransportException("$@", Thrift::TTransportException::UNKNOWN);
+        }
+    };
+    if($@){
+        die Thrift::TTransportException->new("$@", Thrift::TTransportException::UNKNOWN);
     }
 
     return $buf;
@@ -173,8 +174,9 @@
 {
     my $self = shift;
 
-    my $ua = LWP::UserAgent->new('timeout' => ($self->{timeout} / 1000),
-      'agent' => 'Perl/THttpClient'
+    my $ua = LWP::UserAgent->new(
+        'timeout' => ($self->{timeout} / 1000),
+        'agent'   => 'Perl/THttpClient'
      );
     $ua->default_header('Accept' => 'application/x-thrift');
     $ua->default_header('Content-Type' => 'application/x-thrift');
@@ -184,8 +186,7 @@
     $out->setpos(0); # rewind
     my $buf = join('', <$out>);
 
-    my $request = new HTTP::Request(POST => $self->{url}, undef, $buf);
-    map { $request->header($_ => $self->{headers}->{$_}) } keys %{$self->{headers}};
+    my $request = HTTP::Request->new(POST => $self->{url}, ($self->{headers} || undef), $buf);
     my $response = $ua->request($request);
     my $content_ref = $response->content_ref;
 
diff --git a/lib/perl/lib/Thrift/MemoryBuffer.pm b/lib/perl/lib/Thrift/MemoryBuffer.pm
index 1e51239..be97ce4 100644
--- a/lib/perl/lib/Thrift/MemoryBuffer.pm
+++ b/lib/perl/lib/Thrift/MemoryBuffer.pm
@@ -35,10 +35,10 @@
     my $bufferSize= shift || 1024;
 
     my $self = {
-        buffer    => '',
-        bufferSize=> $bufferSize,
-        wPos      => 0,
-        rPos      => 0,
+        buffer     => '',
+        bufferSize => $bufferSize,
+        wPos       => 0,
+        rPos       => 0,
     };
 
     return bless($self,$classname);
@@ -117,7 +117,7 @@
 
     my $avail = ($self->{wPos} - $self->{rPos});
     if ($avail < $len) {
-        die new TTransportException("Attempt to readAll($len) found only $avail available",
+        die TTransportException->new("Attempt to readAll($len) found only $avail available",
                                     Thrift::TTransportException::END_OF_FILE);
     }
 
diff --git a/lib/perl/lib/Thrift/MultiplexedProcessor.pm b/lib/perl/lib/Thrift/MultiplexedProcessor.pm
index 05c4ead..ae925d7 100644
--- a/lib/perl/lib/Thrift/MultiplexedProcessor.pm
+++ b/lib/perl/lib/Thrift/MultiplexedProcessor.pm
@@ -101,32 +101,32 @@
     $input->readMessageBegin(\$fname, \$mtype, \$rseqid);
 
     if ($mtype ne Thrift::TMessageType::CALL && $mtype ne Thrift::TMessageType::ONEWAY) {
-        die new Thrift::TException("This should not have happened!?");
+        die Thrift::TException->new('This should not have happened!?');
     }
 
     # Extract the service name and the new Message name.
     if (index($fname, Thrift::MultiplexedProtocol::SEPARATOR) == -1) {
         if (defined $self->{defaultProcessor}) {
             return $self->{defaultProcessor}->process(
-                new Thrift::StoredMessageProtocol($input, $fname, $mtype, $rseqid), $output
+                Thrift::StoredMessageProtocol->new($input, $fname, $mtype, $rseqid), $output
             );
         } else {
-            die new Thrift::TException("Service name not found in message name: {$fname} and no default processor defined. Did you " .
-                "forget to use a MultiplexProtocol in your client?");
+            die Thrift::TException->new("Service name not found in message name: {$fname} and no default processor defined. Did you " .
+                'forget to use a MultiplexProtocol in your client?');
         }
     }
 
     (my $serviceName, my $messageName) = split(':', $fname, 2);
 
     if (!exists($self->{serviceProcessorMap}->{$serviceName})) {
-        die new Thrift::TException("Service name not found: {$serviceName}.  Did you forget " .
-            "to call registerProcessor()?");
+        die Thrift::TException->new("Service name not found: {$serviceName}.  Did you forget " .
+            'to call registerProcessor()?');
     }
 
     # Dispatch processing to the stored processor
     my $processor = $self->{serviceProcessorMap}->{$serviceName};
     return $processor->process(
-        new Thrift::StoredMessageProtocol($input, $messageName, $mtype, $rseqid), $output
+        Thrift::StoredMessageProtocol->new($input, $messageName, $mtype, $rseqid), $output
     );
 }
 
diff --git a/lib/perl/lib/Thrift/MultiplexedProtocol.pm b/lib/perl/lib/Thrift/MultiplexedProtocol.pm
index 903211f..5b5b60b 100644
--- a/lib/perl/lib/Thrift/MultiplexedProtocol.pm
+++ b/lib/perl/lib/Thrift/MultiplexedProtocol.pm
@@ -53,7 +53,7 @@
 #
 sub writeMessageBegin
 {
-  my $self = shift;
+    my $self = shift;
     my ($name, $type, $seqid) = @_;
 
     if ($type == Thrift::TMessageType::CALL || $type == Thrift::TMessageType::ONEWAY) {
diff --git a/lib/perl/lib/Thrift/Protocol.pm b/lib/perl/lib/Thrift/Protocol.pm
index c681f60..26ef46a 100644
--- a/lib/perl/lib/Thrift/Protocol.pm
+++ b/lib/perl/lib/Thrift/Protocol.pm
@@ -81,14 +81,14 @@
 sub writeMessageBegin
 {
     my ($name, $type, $seqid);
-    die "abstract";
+    die 'abstract';
 }
 
 #
 # Close the message
 #
 sub writeMessageEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -101,7 +101,7 @@
 sub writeStructBegin {
     my ($name);
 
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -111,7 +111,7 @@
 # @return int How many bytes written
 #
 sub writeStructEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -126,79 +126,79 @@
 sub writeFieldBegin {
     my ($fieldName, $fieldType, $fieldId);
 
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeFieldEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeFieldStop {
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeMapBegin {
     my ($keyType, $valType, $size);
 
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeMapEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeListBegin {
     my ($elemType, $size);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeListEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeSetBegin {
     my ($elemType, $size);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeSetEnd {
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeBool {
     my ($bool);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeByte {
     my ($byte);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeI16 {
     my ($i16);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeI32 {
     my ($i32);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeI64 {
     my ($i64);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeDouble {
     my ($dub);
-    die "abstract";
+    die 'abstract';
 }
 
 sub writeString
 {
     my ($str);
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -211,7 +211,7 @@
 sub readMessageBegin
 {
     my ($name, $type, $seqid);
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -219,105 +219,105 @@
 #
 sub readMessageEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readStructBegin
 {
     my($name);
 
-    die "abstract";
+    die 'abstract';
 }
 
 sub readStructEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readFieldBegin
 {
     my ($name, $fieldType, $fieldId);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readFieldEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readMapBegin
 {
     my ($keyType, $valType, $size);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readMapEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readListBegin
 {
     my ($elemType, $size);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readListEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readSetBegin
 {
     my ($elemType, $size);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readSetEnd
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub readBool
 {
     my ($bool);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readByte
 {
     my ($byte);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readI16
 {
     my ($i16);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readI32
 {
     my ($i32);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readI64
 {
     my ($i64);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readDouble
 {
     my ($dub);
-    die "abstract";
+    die 'abstract';
 }
 
 sub readString
 {
     my ($str);
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -405,7 +405,7 @@
         return $result;
     }
 
-    die new Thrift::TProtocolException("Type $type not recognized --- corrupt data?",
+    die Thrift::TProtocolException->new("Type $type not recognized --- corrupt data?",
                                        Thrift::TProtocolException::INVALID_DATA);
 
   }
@@ -424,7 +424,7 @@
 
     if($type == Thrift::TType::BOOL)
     {
-      return $itrans->readAll(1);
+        return $itrans->readAll(1);
     }
     elsif($type == Thrift::TType::BYTE)
     {
@@ -459,17 +459,17 @@
     {
         my $result = 0;
         while (1) {
-          my $ftype = 0;
-          my $fid = 0;
-          my $data = $itrans->readAll(1);
-          my @arr = unpack('c', $data);
-          $ftype = $arr[0];
-          if ($ftype == Thrift::TType::STOP) {
-            last;
-          }
-          # I16 field id
-          $result += $itrans->readAll(2);
-          $result += $self->skipBinary($itrans, $ftype);
+            my $ftype = 0;
+            my $fid = 0;
+            my $data = $itrans->readAll(1);
+            my @arr = unpack('c', $data);
+            $ftype = $arr[0];
+            if ($ftype == Thrift::TType::STOP) {
+                last;
+            }
+            # I16 field id
+            $result += $itrans->readAll(2);
+            $result += $self->skipBinary($itrans, $ftype);
         }
         return $result;
     }
@@ -517,7 +517,7 @@
         return $result;
     }
 
-    die new Thrift::TProtocolException("Type $type not recognized --- corrupt data?",
+    die Thrift::TProtocolException->new("Type $type not recognized --- corrupt data?",
                                        Thrift::TProtocolException::INVALID_DATA);
 }
 
@@ -542,7 +542,7 @@
 sub getProtocol
 {
     my ($trans);
-    die "interface";
+    die 'interface';
 }
 
 
diff --git a/lib/perl/lib/Thrift/SSLServerSocket.pm b/lib/perl/lib/Thrift/SSLServerSocket.pm
index d29671b..7b06431 100644
--- a/lib/perl/lib/Thrift/SSLServerSocket.pm
+++ b/lib/perl/lib/Thrift/SSLServerSocket.pm
@@ -48,7 +48,7 @@
 
 sub __client
 {
-  return new Thrift::SSLSocket();
+  return Thrift::SSLSocket->new();
 }
 
 sub __listen
diff --git a/lib/perl/lib/Thrift/SSLSocket.pm b/lib/perl/lib/Thrift/SSLSocket.pm
index 4bdf637..e34924d 100644
--- a/lib/perl/lib/Thrift/SSLSocket.pm
+++ b/lib/perl/lib/Thrift/SSLSocket.pm
@@ -34,7 +34,7 @@
 # Construction and usage
 #
 # my $opts = {}
-# my $socket = new Thrift::SSLSocket(\%opts);
+# my $socket = Thrift::SSLSocket->new(\%opts);
 #
 # options:
 #
diff --git a/lib/perl/lib/Thrift/Server.pm b/lib/perl/lib/Thrift/Server.pm
index fc9ca30..28822e8 100644
--- a/lib/perl/lib/Thrift/Server.pm
+++ b/lib/perl/lib/Thrift/Server.pm
@@ -51,7 +51,7 @@
 
     if (scalar @args == 2)
     {
-      $self = _init($args[0], $args[1],
+        $self = _init($args[0], $args[1],
                     Thrift::BufferedTransportFactory->new(),
                     Thrift::BufferedTransportFactory->new(),
                     Thrift::BinaryProtocolFactory->new(),
@@ -67,7 +67,7 @@
     }
     else
     {
-      die new Thrift::TException("Thrift::Server expects exactly 2, 4, or 6 args");
+      die Thrift::TException->new('Thrift::Server expects exactly 2, 4, or 6 args');
     }
 
     return bless($self,$classname);
@@ -94,7 +94,7 @@
 
 sub serve
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub _clientBegin
@@ -115,7 +115,7 @@
     my $self = shift;
     my $e    = shift;
 
-    if ($e->isa("Thrift::TException") and exists $e->{message}) {
+    if ($e->isa('Thrift::TException') and exists $e->{message}) {
         my $message = $e->{message};
         my $code    = $e->{code};
         my $out     = $code . ':' . $message;
@@ -123,10 +123,12 @@
         $message =~ m/TTransportException/ and die $out;
         if ($message =~ m/Socket/) {
             # suppress Socket messages
-        } else {
+        }
+        else {
             warn $out;
         }
-    } else {
+    }
+    else {
         warn $e;
     }
 }
@@ -150,27 +152,31 @@
 sub serve
 {
     my $self = shift;
+    my $stop = 0;
 
     $self->{serverTransport}->listen();
-    while (1)
-    {
+    while (!$stop) {
         my $client = $self->{serverTransport}->accept();
-        my $itrans = $self->{inputTransportFactory}->getTransport($client);
-        my $otrans = $self->{outputTransportFactory}->getTransport($client);
-        my $iprot  = $self->{inputProtocolFactory}->getProtocol($itrans);
-        my $oprot  = $self->{outputProtocolFactory}->getProtocol($otrans);
-        eval {
-            $self->_clientBegin($iprot, $oprot);
-            while (1)
-            {
-                $self->{processor}->process($iprot, $oprot);
+        if (defined $client) {
+            my $itrans = $self->{inputTransportFactory}->getTransport($client);
+            my $otrans = $self->{outputTransportFactory}->getTransport($client);
+            my $iprot  = $self->{inputProtocolFactory}->getProtocol($itrans);
+            my $oprot  = $self->{outputProtocolFactory}->getProtocol($otrans);
+            eval {
+                $self->_clientBegin($iprot, $oprot);
+                while (1)
+                {
+                    $self->{processor}->process($iprot, $oprot);
+                }
+            };
+            if($@) {
+                $self->_handleException($@);
             }
-        }; if($@) {
-            $self->_handleException($@);
+            $itrans->close();
+            $otrans->close();
+        } else {
+            $stop = 1;
         }
-
-        $itrans->close();
-        $otrans->close();
     }
 }
 
@@ -180,7 +186,7 @@
 #
 package Thrift::ForkingServer;
 use parent -norequire, 'Thrift::Server';
-use POSIX ":sys_wait_h";
+use POSIX ':sys_wait_h';
 use version 0.77; our $VERSION = version->declare("$Thrift::VERSION");
 
 sub new
@@ -227,10 +233,12 @@
         if ($pid)
         {
             $self->_parent($pid, $itrans, $otrans);
-        } else {
+        }
+        else {
             $self->_child($itrans, $otrans, $iprot, $oprot);
         }
-    }; if($@) {
+    };
+    if($@) {
         $self->_handleException($@);
     }
 }
@@ -263,7 +271,8 @@
         {
             $self->{processor}->process($iprot, $oprot);
         }
-    }; if($@) {
+    };
+    if($@) {
         $ecode = 1;
         $self->_handleException($@);
     }
@@ -284,14 +293,16 @@
         {
           $file->close();
         }
-    }; if($@) {
-        if ($@->isa("Thrift::TException") and exists $@->{message}) {
+    };
+    if($@) {
+        if ($@->isa('Thrift::TException') and exists $@->{message}) {
             my $message = $@->{message};
             my $code    = $@->{code};
             my $out     = $code . ':' . $message;
 
             warn $out;
-        } else {
+        }
+        else {
             warn $@;
         }
     }
diff --git a/lib/perl/lib/Thrift/ServerSocket.pm b/lib/perl/lib/Thrift/ServerSocket.pm
index 51f83b4..3972643 100644
--- a/lib/perl/lib/Thrift/ServerSocket.pm
+++ b/lib/perl/lib/Thrift/ServerSocket.pm
@@ -38,7 +38,7 @@
 # @param[in]  host   host interface to listen on (undef = all interfaces)
 # @param[in]  port   port number to listen on (required)
 # @param[in]  queue  the listen queue size (default if not specified is 128)
-# @example    my $serversock = new Thrift::ServerSocket(host => undef, port => port)
+# @example    my $serversock = Thrift::ServerSocket->new(host => undef, port => port)
 #
 sub new
 {
@@ -49,7 +49,8 @@
     # Support both old-style "port number" construction and newer...
     if (ref($args) eq 'HASH') {
         $self = $args;
-    } else {
+    }
+    else {
         $self = { port => $args };
     }
 
@@ -71,7 +72,7 @@
             $self->{debugHandler}->($error);
         }
 
-        die new Thrift::TTransportException($error, Thrift::TTransportException::NOT_OPEN);
+        die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN);
     };
 
     $self->{handle} = $sock;
@@ -81,15 +82,24 @@
 {
     my $self = shift;
 
-    if ( exists $self->{handle} and defined $self->{handle} )
-    {
+    if ( exists $self->{handle} and defined $self->{handle} ) {
         my $client        = $self->{handle}->accept();
         my $result        = $self->__client();
-        $result->{handle} = new IO::Select($client);
+        $result->{handle} = IO::Select->new($client);
         return $result;
     }
 
-    return 0;
+    return undef;
+}
+
+sub close
+{
+    my $self = shift;
+
+    if ( exists $self->{handle} and defined $self->{handle} )
+    {
+        $self->{handle}->close();
+    }
 }
 
 ###
@@ -98,7 +108,7 @@
 
 sub __client
 {
-  return new Thrift::Socket();
+  return Thrift::Socket->new();
 }
 
 sub __listen
diff --git a/lib/perl/lib/Thrift/Socket.pm b/lib/perl/lib/Thrift/Socket.pm
index ae248df..ba0db5e 100644
--- a/lib/perl/lib/Thrift/Socket.pm
+++ b/lib/perl/lib/Thrift/Socket.pm
@@ -36,7 +36,7 @@
 # Construction and usage
 #
 # my $opts = {}
-# my $socket = new Thrift::Socket(\%opts);
+# my $socket = Thrift::Socket->new(\%opts);
 #
 # options:
 #
@@ -120,10 +120,10 @@
 
     my $sock = $self->__open() || do {
         my $error = ref($self).': Could not connect to '.$self->{host}.':'.$self->{port}.' ('.$!.')';
-        die new Thrift::TTransportException($error, Thrift::TTransportException::NOT_OPEN);
+        die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN);
     };
 
-    $self->{handle} = new IO::Select( $sock );
+    $self->{handle} = IO::Select->new( $sock );
 }
 
 #
@@ -159,15 +159,17 @@
 
         if (!defined $buf || $buf eq '') {
 
-            die new Thrift::TTransportException(ref($self).': Could not read '.$len.' bytes from '.
+            die Thrift::TTransportException->new(ref($self).': Could not read '.$len.' bytes from '.
                                $self->{host}.':'.$self->{port}, Thrift::TTransportException::END_OF_FILE);
 
-        } elsif ((my $sz = length($buf)) < $len) {
+        }
+        elsif ((my $sz = length($buf)) < $len) {
 
             $pre .= $buf;
             $len -= $sz;
 
-        } else {
+        }
+        else {
             return $pre.$buf;
         }
     }
@@ -191,7 +193,7 @@
 
     if (!defined $buf || $buf eq '') {
 
-        die new Thrift::TTransportException(ref($self).': Could not read '.$len.' bytes from '.
+        die Thrift::TTransportException->new(ref($self).': Could not read '.$len.' bytes from '.
                            $self->{host}.':'.$self->{port}, Thrift::TTransportException::END_OF_FILE);
 
     }
@@ -217,7 +219,7 @@
         my @sockets = $self->{handle}->can_write( $self->{sendTimeout} / 1000 );
 
         if(@sockets == 0){
-            die new Thrift::TTransportException(ref($self).': timed out writing to bytes from '.
+            die Thrift::TTransportException->new(ref($self).': timed out writing to bytes from '.
                                        $self->{host}.':'.$self->{port}, Thrift::TTransportException::TIMED_OUT);
         }
 
@@ -225,7 +227,7 @@
 
         if (!defined $sent || $sent == 0 ) {
 
-            die new Thrift::TTransportException(ref($self).': Could not write '.length($buf).' bytes '.
+            die Thrift::TTransportException->new(ref($self).': Could not write '.length($buf).' bytes '.
                                  $self->{host}.':'.$self->{host}, Thrift::TTransportException::END_OF_FILE);
 
         }
@@ -314,7 +316,7 @@
     my @sockets = $self->{handle}->can_read( $self->{recvTimeout} / 1000 );
 
     if (@sockets == 0) {
-        die new Thrift::TTransportException(ref($self).': timed out reading from '.
+        die Thrift::TTransportException->new(ref($self).': timed out reading from '.
                                    $self->{host}.':'.$self->{port}, Thrift::TTransportException::TIMED_OUT);
     }
 
diff --git a/lib/perl/lib/Thrift/Transport.pm b/lib/perl/lib/Thrift/Transport.pm
index 10c8ce2..41b7e15 100644
--- a/lib/perl/lib/Thrift/Transport.pm
+++ b/lib/perl/lib/Thrift/Transport.pm
@@ -54,7 +54,7 @@
 #
 sub isOpen
 {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -64,7 +64,7 @@
 #
 sub open
 {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -72,7 +72,7 @@
 #
 sub close
 {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -84,7 +84,7 @@
 #
 sub read
 {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -116,7 +116,7 @@
 #
 sub write
 {
-    die "abstract";
+    die 'abstract';
 }
 
 #
@@ -162,17 +162,17 @@
 
 sub listen
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub accept
 {
-    die "abstract";
+    die 'abstract';
 }
 
 sub close
 {
-    die "abstract";
+    die 'abstract';
 }
 
 
diff --git a/lib/perl/lib/Thrift/UnixServerSocket.pm b/lib/perl/lib/Thrift/UnixServerSocket.pm
index 7b857ce..875e804 100644
--- a/lib/perl/lib/Thrift/UnixServerSocket.pm
+++ b/lib/perl/lib/Thrift/UnixServerSocket.pm
@@ -37,8 +37,8 @@
 # If a single argument is given that is a hash:
 # @param[in]  path   unix domain socket file name
 # @param[in]  queue  the listen queue size (default is not specified is supplied by ServerSocket)
-# @example    my $serversock = new Thrift::UnixServerSocket($path);
-# @example    my $serversock = new Thrift::UnixServerSocket(path => "somepath", queue => 64);
+# @example    my $serversock = Thrift::UnixServerSocket->new($path);
+# @example    my $serversock = Thrift::UnixServerSocket->new(path => "somepath", queue => 64);
 #
 sub new
 {
@@ -58,7 +58,7 @@
 
 sub __client
 {
-  return new Thrift::UnixSocket();
+  return Thrift::UnixSocket->new();
 }
 
 sub __listen
@@ -75,7 +75,7 @@
         if ($self->{debug}) {
             $self->{debugHandler}->($error);
         }
-        die new Thrift::TTransportException($error, Thrift::TTransportException::NOT_OPEN);
+        die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN);
     };
 
     return $sock;
diff --git a/lib/perl/lib/Thrift/UnixSocket.pm b/lib/perl/lib/Thrift/UnixSocket.pm
index 8b00450..ba386d1 100644
--- a/lib/perl/lib/Thrift/UnixSocket.pm
+++ b/lib/perl/lib/Thrift/UnixSocket.pm
@@ -35,7 +35,7 @@
 # Takes a unix domain socket filename.
 # See Thrift::Socket for base class parameters.
 # @param[in]  path   path to unix socket file
-# @example    my $sock = new Thrift::UnixSocket($path);
+# @example    my $sock = Thrift::UnixSocket->new($path);
 #
 sub new
 {
@@ -58,7 +58,7 @@
         if ($self->{debug}) {
             $self->{debugHandler}->($error);
         }
-        die new Thrift::TTransportException($error, Thrift::TTransportException::NOT_OPEN);
+        die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN);
     };
 
     return $sock;
diff --git a/lib/perl/tools/FixupDist.pl b/lib/perl/tools/FixupDist.pl
new file mode 100644
index 0000000..24a2b20
--- /dev/null
+++ b/lib/perl/tools/FixupDist.pl
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+#
+# This will fix up the distribution so that CPAN properly
+# indexes Thrift.
+#
+
+use 5.10.0;
+use strict;
+use warnings;
+use utf8;
+
+use Data::Dumper;
+use CPAN::Meta;
+
+my $meta = CPAN::Meta->load_file('META.json');
+$meta->{'provides'} = { 'Thrift' => { 'file' => 'lib/Thrift.pm', 'version' => $meta->version() } };
+$meta->save('META.json');
diff --git a/lib/php/Makefile.am b/lib/php/Makefile.am
index 5aa3be4..8d9050a 100755
--- a/lib/php/Makefile.am
+++ b/lib/php/Makefile.am
@@ -37,96 +37,96 @@
 
 endif
 
-phpdir = $(PHP_PREFIX)/Thrift
+phpdir = $(PHP_PREFIX)/
 php_DATA = \
-  lib/Thrift/TMultiplexedProcessor.php
+  lib/TMultiplexedProcessor.php
 
 phpbasedir = $(phpdir)/Base
 phpbase_DATA = \
-  lib/Thrift/Base/TBase.php
+  lib/Base/TBase.php
 
 phpclassloaderdir = $(phpdir)/ClassLoader
 phpclassloader_DATA = \
-  lib/Thrift/ClassLoader/ThriftClassLoader.php
+  lib/ClassLoader/ThriftClassLoader.php
 
 phpexceptiondir = $(phpdir)/Exception
 phpexception_DATA = \
-  lib/Thrift/Exception/TApplicationException.php \
-  lib/Thrift/Exception/TException.php \
-  lib/Thrift/Exception/TProtocolException.php \
-  lib/Thrift/Exception/TTransportException.php
+  lib/Exception/TApplicationException.php \
+  lib/Exception/TException.php \
+  lib/Exception/TProtocolException.php \
+  lib/Exception/TTransportException.php
 
 phpfactorydir = $(phpdir)/Factory
 phpfactory_DATA = \
-  lib/Thrift/Factory/TBinaryProtocolFactory.php \
-  lib/Thrift/Factory/TCompactProtocolFactory.php \
-  lib/Thrift/Factory/TJSONProtocolFactory.php \
-  lib/Thrift/Factory/TProtocolFactory.php \
-  lib/Thrift/Factory/TStringFuncFactory.php \
-  lib/Thrift/Factory/TTransportFactory.php
+  lib/Factory/TBinaryProtocolFactory.php \
+  lib/Factory/TCompactProtocolFactory.php \
+  lib/Factory/TJSONProtocolFactory.php \
+  lib/Factory/TProtocolFactory.php \
+  lib/Factory/TStringFuncFactory.php \
+  lib/Factory/TTransportFactory.php
 
 phpprotocoldir = $(phpdir)/Protocol
 phpprotocol_DATA = \
-  lib/Thrift/Protocol/TBinaryProtocolAccelerated.php \
-  lib/Thrift/Protocol/TBinaryProtocol.php \
-  lib/Thrift/Protocol/TCompactProtocol.php \
-  lib/Thrift/Protocol/TJSONProtocol.php \
-  lib/Thrift/Protocol/TMultiplexedProtocol.php \
-  lib/Thrift/Protocol/TProtocol.php \
-  lib/Thrift/Protocol/TProtocolDecorator.php \
-  lib/Thrift/Protocol/TSimpleJSONProtocol.php
+  lib/Protocol/TBinaryProtocolAccelerated.php \
+  lib/Protocol/TBinaryProtocol.php \
+  lib/Protocol/TCompactProtocol.php \
+  lib/Protocol/TJSONProtocol.php \
+  lib/Protocol/TMultiplexedProtocol.php \
+  lib/Protocol/TProtocol.php \
+  lib/Protocol/TProtocolDecorator.php \
+  lib/Protocol/TSimpleJSONProtocol.php
 
 phpprotocoljsondir = $(phpprotocoldir)/JSON
 phpprotocoljson_DATA = \
-  lib/Thrift/Protocol/JSON/BaseContext.php \
-  lib/Thrift/Protocol/JSON/ListContext.php \
-  lib/Thrift/Protocol/JSON/LookaheadReader.php \
-  lib/Thrift/Protocol/JSON/PairContext.php
+  lib/Protocol/JSON/BaseContext.php \
+  lib/Protocol/JSON/ListContext.php \
+  lib/Protocol/JSON/LookaheadReader.php \
+  lib/Protocol/JSON/PairContext.php
 
 phpprotocolsimplejsondir = $(phpprotocoldir)/SimpleJSON
 phpprotocolsimplejson_DATA = \
-  lib/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php \
-  lib/Thrift/Protocol/SimpleJSON/Context.php \
-  lib/Thrift/Protocol/SimpleJSON/ListContext.php \
-  lib/Thrift/Protocol/SimpleJSON/MapContext.php \
-  lib/Thrift/Protocol/SimpleJSON/StructContext.php
+  lib/Protocol/SimpleJSON/CollectionMapKeyException.php \
+  lib/Protocol/SimpleJSON/Context.php \
+  lib/Protocol/SimpleJSON/ListContext.php \
+  lib/Protocol/SimpleJSON/MapContext.php \
+  lib/Protocol/SimpleJSON/StructContext.php
 
 phpserializerdir = $(phpdir)/Serializer
 phpserializer_DATA = \
-  lib/Thrift/Serializer/TBinarySerializer.php
+  lib/Serializer/TBinarySerializer.php
 
 phpserverdir = $(phpdir)/Server
 phpserver_DATA = \
-  lib/Thrift/Server/TServerSocket.php \
-  lib/Thrift/Server/TForkingServer.php \
-  lib/Thrift/Server/TServer.php \
-  lib/Thrift/Server/TServerTransport.php \
-  lib/Thrift/Server/TSimpleServer.php
+  lib/Server/TServerSocket.php \
+  lib/Server/TForkingServer.php \
+  lib/Server/TServer.php \
+  lib/Server/TServerTransport.php \
+  lib/Server/TSimpleServer.php
 
 phpstringfuncdir = $(phpdir)/StringFunc
 phpstringfunc_DATA = \
-  lib/Thrift/StringFunc/Mbstring.php \
-  lib/Thrift/StringFunc/Core.php \
-  lib/Thrift/StringFunc/TStringFunc.php
+  lib/StringFunc/Mbstring.php \
+  lib/StringFunc/Core.php \
+  lib/StringFunc/TStringFunc.php
 
 phptransportdir = $(phpdir)/Transport
 phptransport_DATA = \
-  lib/Thrift/Transport/TBufferedTransport.php \
-  lib/Thrift/Transport/TCurlClient.php \
-  lib/Thrift/Transport/TFramedTransport.php \
-  lib/Thrift/Transport/THttpClient.php \
-  lib/Thrift/Transport/TMemoryBuffer.php \
-  lib/Thrift/Transport/TNullTransport.php \
-  lib/Thrift/Transport/TPhpStream.php \
-  lib/Thrift/Transport/TSocket.php \
-  lib/Thrift/Transport/TSocketPool.php \
-  lib/Thrift/Transport/TTransport.php
+  lib/Transport/TBufferedTransport.php \
+  lib/Transport/TCurlClient.php \
+  lib/Transport/TFramedTransport.php \
+  lib/Transport/THttpClient.php \
+  lib/Transport/TMemoryBuffer.php \
+  lib/Transport/TNullTransport.php \
+  lib/Transport/TPhpStream.php \
+  lib/Transport/TSocket.php \
+  lib/Transport/TSocketPool.php \
+  lib/Transport/TTransport.php
 
 phptypedir = $(phpdir)/Type
 phptype_DATA = \
-  lib/Thrift/Type/TMessageType.php \
-  lib/Thrift/Type/TType.php \
-  lib/Thrift/Type/TConstant.php
+  lib/Type/TMessageType.php \
+  lib/Type/TType.php \
+  lib/Type/TConstant.php
 
 EXTRA_DIST = \
   lib \
diff --git a/lib/php/README.md b/lib/php/README.md
index c24ee2c..7170104 100644
--- a/lib/php/README.md
+++ b/lib/php/README.md
@@ -1,7 +1,6 @@
 Thrift PHP Software Library
 
-License
-=======
+# License
 
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements. See the NOTICE file
@@ -20,8 +19,7 @@
 specific language governing permissions and limitations
 under the License.
 
-Using Thrift with PHP
-=====================
+# Using Thrift with PHP
 
 Thrift requires PHP 5. Thrift makes as few assumptions about your PHP
 environment as possible while trying to make some more advanced PHP
@@ -29,25 +27,34 @@
 
 To use Thrift in your PHP codebase, take the following steps:
 
-#1) Copy all of thrift/lib/php/lib into your PHP codebase
-#2) Configure Symfony Autoloader (or whatever you usually use)
+1. Copy all of thrift/lib/php/lib into your PHP codebase
+2. Configure Symfony Autoloader (or whatever you usually use)
 
 After that, you have to manually include the Thrift package
 created by the compiler:
 
+```
 require_once 'packages/Service/Service.php';
 require_once 'packages/Service/Types.php';
+```
 
-Dependencies
-============
+# Dependencies
 
 PHP_INT_SIZE
 
-  This built-in signals whether your architecture is 32 or 64 bit and is
-  used by the TBinaryProtocol to properly use pack() and unpack() to
-  serialize data.
+    This built-in signals whether your architecture is 32 or 64 bit and is
+    used by the TBinaryProtocol to properly use pack() and unpack() to
+    serialize data.
 
 apc_fetch(), apc_store()
 
-  APC cache is used by the TSocketPool class. If you do not have APC installed,
-  Thrift will fill in null stub function definitions.
+    APC cache is used by the TSocketPool class. If you do not have APC installed,
+    Thrift will fill in null stub function definitions.
+
+# Breaking Changes
+
+## 0.12.0
+
+1. [PSR-4](https://www.php-fig.org/psr/psr-4/) loader is now the default. If you want to use class maps instead, use `-gen php:classmap`.
+
+2. If using PSR-4, use `$thriftClassLoader->registerNamespace('namespace', '<path>')` instead of `$thriftClassLoader->registerDefinition('namespace', '<path>')`.
diff --git a/lib/php/coding_standards.md b/lib/php/coding_standards.md
index fa0390b..e217539 100644
--- a/lib/php/coding_standards.md
+++ b/lib/php/coding_standards.md
@@ -1 +1,5 @@
-Please follow [General Coding Standards](/doc/coding_standards.md)
+## PHP Coding Standards
+
+Please follow:
+ * [Thrift General Coding Standards](/doc/coding_standards.md)
+ * [PSR-2](http://www.php-fig.org/psr/psr-2/)
diff --git a/lib/php/lib/Base/TBase.php b/lib/php/lib/Base/TBase.php
new file mode 100644
index 0000000..c61b631
--- /dev/null
+++ b/lib/php/lib/Base/TBase.php
@@ -0,0 +1,382 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift
+ */
+
+namespace Thrift\Base;
+
+use Thrift\Type\TType;
+
+/**
+ * Base class from which other Thrift structs extend. This is so that we can
+ * cut back on the size of the generated code which is turning out to have a
+ * nontrivial cost just to load thanks to the wondrously abysmal implementation
+ * of PHP. Note that code is intentionally duplicated in here to avoid making
+ * function calls for every field or member of a container..
+ */
+abstract class TBase
+{
+    public static $tmethod = array(
+        TType::BOOL => 'Bool',
+        TType::BYTE => 'Byte',
+        TType::I16 => 'I16',
+        TType::I32 => 'I32',
+        TType::I64 => 'I64',
+        TType::DOUBLE => 'Double',
+        TType::STRING => 'String'
+    );
+
+    abstract public function read($input);
+
+    abstract public function write($output);
+
+    public function __construct($spec = null, $vals = null)
+    {
+        if (is_array($spec) && is_array($vals)) {
+            foreach ($spec as $fid => $fspec) {
+                $var = $fspec['var'];
+                if (isset($vals[$var])) {
+                    $this->$var = $vals[$var];
+                }
+            }
+        }
+    }
+
+    public function __wakeup()
+    {
+        $this->__construct(get_object_vars($this));
+    }
+
+    private function _readMap(&$var, $spec, $input)
+    {
+        $xfer = 0;
+        $ktype = $spec['ktype'];
+        $vtype = $spec['vtype'];
+        $kread = $vread = null;
+        if (isset(TBase::$tmethod[$ktype])) {
+            $kread = 'read' . TBase::$tmethod[$ktype];
+        } else {
+            $kspec = $spec['key'];
+        }
+        if (isset(TBase::$tmethod[$vtype])) {
+            $vread = 'read' . TBase::$tmethod[$vtype];
+        } else {
+            $vspec = $spec['val'];
+        }
+        $var = array();
+        $_ktype = $_vtype = $size = 0;
+        $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
+        for ($i = 0; $i < $size; ++$i) {
+            $key = $val = null;
+            if ($kread !== null) {
+                $xfer += $input->$kread($key);
+            } else {
+                switch ($ktype) {
+                    case TType::STRUCT:
+                        $class = $kspec['class'];
+                        $key = new $class();
+                        $xfer += $key->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($key, $kspec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($key, $kspec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($key, $kspec, $input, true);
+                        break;
+                }
+            }
+            if ($vread !== null) {
+                $xfer += $input->$vread($val);
+            } else {
+                switch ($vtype) {
+                    case TType::STRUCT:
+                        $class = $vspec['class'];
+                        $val = new $class();
+                        $xfer += $val->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($val, $vspec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($val, $vspec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($val, $vspec, $input, true);
+                        break;
+                }
+            }
+            $var[$key] = $val;
+        }
+        $xfer += $input->readMapEnd();
+
+        return $xfer;
+    }
+
+    private function _readList(&$var, $spec, $input, $set = false)
+    {
+        $xfer = 0;
+        $etype = $spec['etype'];
+        $eread = $vread = null;
+        if (isset(TBase::$tmethod[$etype])) {
+            $eread = 'read' . TBase::$tmethod[$etype];
+        } else {
+            $espec = $spec['elem'];
+        }
+        $var = array();
+        $_etype = $size = 0;
+        if ($set) {
+            $xfer += $input->readSetBegin($_etype, $size);
+        } else {
+            $xfer += $input->readListBegin($_etype, $size);
+        }
+        for ($i = 0; $i < $size; ++$i) {
+            $elem = null;
+            if ($eread !== null) {
+                $xfer += $input->$eread($elem);
+            } else {
+                $espec = $spec['elem'];
+                switch ($etype) {
+                    case TType::STRUCT:
+                        $class = $espec['class'];
+                        $elem = new $class();
+                        $xfer += $elem->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($elem, $espec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($elem, $espec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($elem, $espec, $input, true);
+                        break;
+                }
+            }
+            if ($set) {
+                $var[$elem] = true;
+            } else {
+                $var [] = $elem;
+            }
+        }
+        if ($set) {
+            $xfer += $input->readSetEnd();
+        } else {
+            $xfer += $input->readListEnd();
+        }
+
+        return $xfer;
+    }
+
+    protected function _read($class, $spec, $input)
+    {
+        $xfer = 0;
+        $fname = null;
+        $ftype = 0;
+        $fid = 0;
+        $xfer += $input->readStructBegin($fname);
+        while (true) {
+            $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+            if ($ftype == TType::STOP) {
+                break;
+            }
+            if (isset($spec[$fid])) {
+                $fspec = $spec[$fid];
+                $var = $fspec['var'];
+                if ($ftype == $fspec['type']) {
+                    $xfer = 0;
+                    if (isset(TBase::$tmethod[$ftype])) {
+                        $func = 'read' . TBase::$tmethod[$ftype];
+                        $xfer += $input->$func($this->$var);
+                    } else {
+                        switch ($ftype) {
+                            case TType::STRUCT:
+                                $class = $fspec['class'];
+                                $this->$var = new $class();
+                                $xfer += $this->$var->read($input);
+                                break;
+                            case TType::MAP:
+                                $xfer += $this->_readMap($this->$var, $fspec, $input);
+                                break;
+                            case TType::LST:
+                                $xfer += $this->_readList($this->$var, $fspec, $input, false);
+                                break;
+                            case TType::SET:
+                                $xfer += $this->_readList($this->$var, $fspec, $input, true);
+                                break;
+                        }
+                    }
+                } else {
+                    $xfer += $input->skip($ftype);
+                }
+            } else {
+                $xfer += $input->skip($ftype);
+            }
+            $xfer += $input->readFieldEnd();
+        }
+        $xfer += $input->readStructEnd();
+
+        return $xfer;
+    }
+
+    private function _writeMap($var, $spec, $output)
+    {
+        $xfer = 0;
+        $ktype = $spec['ktype'];
+        $vtype = $spec['vtype'];
+        $kwrite = $vwrite = null;
+        if (isset(TBase::$tmethod[$ktype])) {
+            $kwrite = 'write' . TBase::$tmethod[$ktype];
+        } else {
+            $kspec = $spec['key'];
+        }
+        if (isset(TBase::$tmethod[$vtype])) {
+            $vwrite = 'write' . TBase::$tmethod[$vtype];
+        } else {
+            $vspec = $spec['val'];
+        }
+        $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
+        foreach ($var as $key => $val) {
+            if (isset($kwrite)) {
+                $xfer += $output->$kwrite($key);
+            } else {
+                switch ($ktype) {
+                    case TType::STRUCT:
+                        $xfer += $key->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($key, $kspec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($key, $kspec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($key, $kspec, $output, true);
+                        break;
+                }
+            }
+            if (isset($vwrite)) {
+                $xfer += $output->$vwrite($val);
+            } else {
+                switch ($vtype) {
+                    case TType::STRUCT:
+                        $xfer += $val->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($val, $vspec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($val, $vspec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($val, $vspec, $output, true);
+                        break;
+                }
+            }
+        }
+        $xfer += $output->writeMapEnd();
+
+        return $xfer;
+    }
+
+    private function _writeList($var, $spec, $output, $set = false)
+    {
+        $xfer = 0;
+        $etype = $spec['etype'];
+        $ewrite = null;
+        if (isset(TBase::$tmethod[$etype])) {
+            $ewrite = 'write' . TBase::$tmethod[$etype];
+        } else {
+            $espec = $spec['elem'];
+        }
+        if ($set) {
+            $xfer += $output->writeSetBegin($etype, count($var));
+        } else {
+            $xfer += $output->writeListBegin($etype, count($var));
+        }
+        foreach ($var as $key => $val) {
+            $elem = $set ? $key : $val;
+            if (isset($ewrite)) {
+                $xfer += $output->$ewrite($elem);
+            } else {
+                switch ($etype) {
+                    case TType::STRUCT:
+                        $xfer += $elem->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($elem, $espec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($elem, $espec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($elem, $espec, $output, true);
+                        break;
+                }
+            }
+        }
+        if ($set) {
+            $xfer += $output->writeSetEnd();
+        } else {
+            $xfer += $output->writeListEnd();
+        }
+
+        return $xfer;
+    }
+
+    protected function _write($class, $spec, $output)
+    {
+        $xfer = 0;
+        $xfer += $output->writeStructBegin($class);
+        foreach ($spec as $fid => $fspec) {
+            $var = $fspec['var'];
+            if ($this->$var !== null) {
+                $ftype = $fspec['type'];
+                $xfer += $output->writeFieldBegin($var, $ftype, $fid);
+                if (isset(TBase::$tmethod[$ftype])) {
+                    $func = 'write' . TBase::$tmethod[$ftype];
+                    $xfer += $output->$func($this->$var);
+                } else {
+                    switch ($ftype) {
+                        case TType::STRUCT:
+                            $xfer += $this->$var->write($output);
+                            break;
+                        case TType::MAP:
+                            $xfer += $this->_writeMap($this->$var, $fspec, $output);
+                            break;
+                        case TType::LST:
+                            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
+                            break;
+                        case TType::SET:
+                            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
+                            break;
+                    }
+                }
+                $xfer += $output->writeFieldEnd();
+            }
+        }
+        $xfer += $output->writeFieldStop();
+        $xfer += $output->writeStructEnd();
+
+        return $xfer;
+    }
+}
diff --git a/lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php b/lib/php/lib/ClassLoader/ThriftClassLoader.php
similarity index 78%
rename from lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php
rename to lib/php/lib/ClassLoader/ThriftClassLoader.php
index 67575ce..4361bd8 100644
--- a/lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php
+++ b/lib/php/lib/ClassLoader/ThriftClassLoader.php
@@ -54,7 +54,7 @@
     /**
      * Set autoloader to use APC cache
      * @param boolean $apc
-     * @param string  $apc_prefix
+     * @param string $apc_prefix
      */
     public function __construct($apc = false, $apc_prefix = null)
     {
@@ -65,23 +65,23 @@
     /**
      * Registers a namespace.
      *
-     * @param string       $namespace The namespace
-     * @param array|string $paths     The location(s) of the namespace
+     * @param string $namespace The namespace
+     * @param array|string $paths The location(s) of the namespace
      */
     public function registerNamespace($namespace, $paths)
     {
-        $this->namespaces[$namespace] = (array) $paths;
+        $this->namespaces[$namespace] = (array)$paths;
     }
 
     /**
      * Registers a Thrift definition namespace.
      *
-     * @param string       $namespace The definition namespace
-     * @param array|string $paths     The location(s) of the definition namespace
+     * @param string $namespace The definition namespace
+     * @param array|string $paths The location(s) of the definition namespace
      */
     public function registerDefinition($namespace, $paths)
     {
-        $this->definitions[$namespace] = (array) $paths;
+        $this->definitions[$namespace] = (array)$paths;
     }
 
     /**
@@ -101,11 +101,9 @@
      */
     public function loadClass($class)
     {
-        if (
-            (true === $this->apc && ($file = $this->findFileInApc($class))) or
+        if ((true === $this->apc && ($file = $this->findFileInApc($class))) or
             ($file = $this->findFile($class))
-        )
-        {
+        ) {
             require_once $file;
         }
     }
@@ -117,8 +115,8 @@
      */
     protected function findFileInApc($class)
     {
-        if (false === $file = apc_fetch($this->apc_prefix.$class)) {
-            apc_store($this->apc_prefix.$class, $file = $this->findFile($class));
+        if (false === $file = apc_fetch($this->apc_prefix . $class)) {
+            apc_store($this->apc_prefix . $class, $file = $this->findFile($class));
         }
 
         return $file;
@@ -150,10 +148,10 @@
                 foreach ($dirs as $dir) {
                     $className = substr($class, $pos + 1);
 
-                    $file = $dir.DIRECTORY_SEPARATOR.
-                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace).
-                                 DIRECTORY_SEPARATOR.
-                                 $className.'.php';
+                    $file = $dir . DIRECTORY_SEPARATOR .
+                        str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
+                        DIRECTORY_SEPARATOR .
+                        $className . '.php';
 
                     if (file_exists($file)) {
                         return $file;
@@ -185,20 +183,18 @@
                      * Available in service: Interface, Client, Processor, Rest
                      * And every service methods (_.+)
                      */
-                    if(
-                        0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and
+                    if (0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and
                         0 === preg_match('#(.+)_[a-z0-9]+_(args|result)$#i', $class, $n)
-                    )
-                    {
+                    ) {
                         $className = 'Types';
                     } else {
                         $className = $n[1];
                     }
 
-                    $file = $dir.DIRECTORY_SEPARATOR .
-                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
-                                 DIRECTORY_SEPARATOR .
-                                 $className . '.php';
+                    $file = $dir . DIRECTORY_SEPARATOR .
+                        str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
+                        DIRECTORY_SEPARATOR .
+                        $className . '.php';
 
                     if (file_exists($file)) {
                         return $file;
diff --git a/lib/php/lib/Exception/TApplicationException.php b/lib/php/lib/Exception/TApplicationException.php
new file mode 100644
index 0000000..ebb6a6a
--- /dev/null
+++ b/lib/php/lib/Exception/TApplicationException.php
@@ -0,0 +1,76 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift
+ */
+
+namespace Thrift\Exception;
+
+use Thrift\Type\TType;
+
+class TApplicationException extends TException
+{
+    public static $_TSPEC =
+        array(1 => array('var' => 'message',
+            'type' => TType::STRING),
+            2 => array('var' => 'code',
+                'type' => TType::I32));
+
+    const UNKNOWN = 0;
+    const UNKNOWN_METHOD = 1;
+    const INVALID_MESSAGE_TYPE = 2;
+    const WRONG_METHOD_NAME = 3;
+    const BAD_SEQUENCE_ID = 4;
+    const MISSING_RESULT = 5;
+    const INTERNAL_ERROR = 6;
+    const PROTOCOL_ERROR = 7;
+    const INVALID_TRANSFORM = 8;
+    const INVALID_PROTOCOL = 9;
+    const UNSUPPORTED_CLIENT_TYPE = 10;
+
+    public function __construct($message = null, $code = 0)
+    {
+        parent::__construct($message, $code);
+    }
+
+    public function read($output)
+    {
+        return $this->_read('TApplicationException', self::$_TSPEC, $output);
+    }
+
+    public function write($output)
+    {
+        $xfer = 0;
+        $xfer += $output->writeStructBegin('TApplicationException');
+        if ($message = $this->getMessage()) {
+            $xfer += $output->writeFieldBegin('message', TType::STRING, 1);
+            $xfer += $output->writeString($message);
+            $xfer += $output->writeFieldEnd();
+        }
+        if ($code = $this->getCode()) {
+            $xfer += $output->writeFieldBegin('type', TType::I32, 2);
+            $xfer += $output->writeI32($code);
+            $xfer += $output->writeFieldEnd();
+        }
+        $xfer += $output->writeFieldStop();
+        $xfer += $output->writeStructEnd();
+
+        return $xfer;
+    }
+}
diff --git a/lib/php/lib/Exception/TException.php b/lib/php/lib/Exception/TException.php
new file mode 100644
index 0000000..7dbf832
--- /dev/null
+++ b/lib/php/lib/Exception/TException.php
@@ -0,0 +1,384 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift
+ */
+
+namespace Thrift\Exception;
+
+use Thrift\Type\TType;
+use Thrift\Base\TBase;
+
+/**
+ * NOTE(mcslee): This currently contains a ton of duplicated code from TBase
+ * because we need to save CPU cycles and this is not yet in an extension.
+ * Ideally we'd multiply-inherit TException from both Exception and Base, but
+ * that's not possible in PHP and there are no modules either, so for now we
+ * apologetically take a trip to HackTown.
+ *
+ * Can be called with standard Exception constructor (message, code) or with
+ * Thrift Base object constructor (spec, vals).
+ *
+ * @param mixed $p1 Message (string) or type-spec (array)
+ * @param mixed $p2 Code (integer) or values (array)
+ */
+class TException extends \Exception
+{
+    public function __construct($p1 = null, $p2 = 0)
+    {
+        if (is_array($p1) && is_array($p2)) {
+            $spec = $p1;
+            $vals = $p2;
+            foreach ($spec as $fid => $fspec) {
+                $var = $fspec['var'];
+                if (isset($vals[$var])) {
+                    $this->$var = $vals[$var];
+                }
+            }
+        } else {
+            parent::__construct($p1, $p2);
+        }
+    }
+
+    public static $tmethod = array(
+        TType::BOOL => 'Bool',
+        TType::BYTE => 'Byte',
+        TType::I16 => 'I16',
+        TType::I32 => 'I32',
+        TType::I64 => 'I64',
+        TType::DOUBLE => 'Double',
+        TType::STRING => 'String'
+    );
+
+    private function _readMap(&$var, $spec, $input)
+    {
+        $xfer = 0;
+        $ktype = $spec['ktype'];
+        $vtype = $spec['vtype'];
+        $kread = $vread = null;
+        if (isset(TBase::$tmethod[$ktype])) {
+            $kread = 'read' . TBase::$tmethod[$ktype];
+        } else {
+            $kspec = $spec['key'];
+        }
+        if (isset(TBase::$tmethod[$vtype])) {
+            $vread = 'read' . TBase::$tmethod[$vtype];
+        } else {
+            $vspec = $spec['val'];
+        }
+        $var = array();
+        $_ktype = $_vtype = $size = 0;
+        $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
+        for ($i = 0; $i < $size; ++$i) {
+            $key = $val = null;
+            if ($kread !== null) {
+                $xfer += $input->$kread($key);
+            } else {
+                switch ($ktype) {
+                    case TType::STRUCT:
+                        $class = $kspec['class'];
+                        $key = new $class();
+                        $xfer += $key->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($key, $kspec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($key, $kspec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($key, $kspec, $input, true);
+                        break;
+                }
+            }
+            if ($vread !== null) {
+                $xfer += $input->$vread($val);
+            } else {
+                switch ($vtype) {
+                    case TType::STRUCT:
+                        $class = $vspec['class'];
+                        $val = new $class();
+                        $xfer += $val->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($val, $vspec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($val, $vspec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($val, $vspec, $input, true);
+                        break;
+                }
+            }
+            $var[$key] = $val;
+        }
+        $xfer += $input->readMapEnd();
+
+        return $xfer;
+    }
+
+    private function _readList(&$var, $spec, $input, $set = false)
+    {
+        $xfer = 0;
+        $etype = $spec['etype'];
+        $eread = $vread = null;
+        if (isset(TBase::$tmethod[$etype])) {
+            $eread = 'read' . TBase::$tmethod[$etype];
+        } else {
+            $espec = $spec['elem'];
+        }
+        $var = array();
+        $_etype = $size = 0;
+        if ($set) {
+            $xfer += $input->readSetBegin($_etype, $size);
+        } else {
+            $xfer += $input->readListBegin($_etype, $size);
+        }
+        for ($i = 0; $i < $size; ++$i) {
+            $elem = null;
+            if ($eread !== null) {
+                $xfer += $input->$eread($elem);
+            } else {
+                $espec = $spec['elem'];
+                switch ($etype) {
+                    case TType::STRUCT:
+                        $class = $espec['class'];
+                        $elem = new $class();
+                        $xfer += $elem->read($input);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_readMap($elem, $espec, $input);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_readList($elem, $espec, $input, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_readList($elem, $espec, $input, true);
+                        break;
+                }
+            }
+            if ($set) {
+                $var[$elem] = true;
+            } else {
+                $var [] = $elem;
+            }
+        }
+        if ($set) {
+            $xfer += $input->readSetEnd();
+        } else {
+            $xfer += $input->readListEnd();
+        }
+
+        return $xfer;
+    }
+
+    protected function _read($class, $spec, $input)
+    {
+        $xfer = 0;
+        $fname = null;
+        $ftype = 0;
+        $fid = 0;
+        $xfer += $input->readStructBegin($fname);
+        while (true) {
+            $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+            if ($ftype == TType::STOP) {
+                break;
+            }
+            if (isset($spec[$fid])) {
+                $fspec = $spec[$fid];
+                $var = $fspec['var'];
+                if ($ftype == $fspec['type']) {
+                    $xfer = 0;
+                    if (isset(TBase::$tmethod[$ftype])) {
+                        $func = 'read' . TBase::$tmethod[$ftype];
+                        $xfer += $input->$func($this->$var);
+                    } else {
+                        switch ($ftype) {
+                            case TType::STRUCT:
+                                $class = $fspec['class'];
+                                $this->$var = new $class();
+                                $xfer += $this->$var->read($input);
+                                break;
+                            case TType::MAP:
+                                $xfer += $this->_readMap($this->$var, $fspec, $input);
+                                break;
+                            case TType::LST:
+                                $xfer += $this->_readList($this->$var, $fspec, $input, false);
+                                break;
+                            case TType::SET:
+                                $xfer += $this->_readList($this->$var, $fspec, $input, true);
+                                break;
+                        }
+                    }
+                } else {
+                    $xfer += $input->skip($ftype);
+                }
+            } else {
+                $xfer += $input->skip($ftype);
+            }
+            $xfer += $input->readFieldEnd();
+        }
+        $xfer += $input->readStructEnd();
+
+        return $xfer;
+    }
+
+    private function _writeMap($var, $spec, $output)
+    {
+        $xfer = 0;
+        $ktype = $spec['ktype'];
+        $vtype = $spec['vtype'];
+        $kwrite = $vwrite = null;
+        if (isset(TBase::$tmethod[$ktype])) {
+            $kwrite = 'write' . TBase::$tmethod[$ktype];
+        } else {
+            $kspec = $spec['key'];
+        }
+        if (isset(TBase::$tmethod[$vtype])) {
+            $vwrite = 'write' . TBase::$tmethod[$vtype];
+        } else {
+            $vspec = $spec['val'];
+        }
+        $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
+        foreach ($var as $key => $val) {
+            if (isset($kwrite)) {
+                $xfer += $output->$kwrite($key);
+            } else {
+                switch ($ktype) {
+                    case TType::STRUCT:
+                        $xfer += $key->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($key, $kspec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($key, $kspec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($key, $kspec, $output, true);
+                        break;
+                }
+            }
+            if (isset($vwrite)) {
+                $xfer += $output->$vwrite($val);
+            } else {
+                switch ($vtype) {
+                    case TType::STRUCT:
+                        $xfer += $val->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($val, $vspec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($val, $vspec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($val, $vspec, $output, true);
+                        break;
+                }
+            }
+        }
+        $xfer += $output->writeMapEnd();
+
+        return $xfer;
+    }
+
+    private function _writeList($var, $spec, $output, $set = false)
+    {
+        $xfer = 0;
+        $etype = $spec['etype'];
+        $ewrite = null;
+        if (isset(TBase::$tmethod[$etype])) {
+            $ewrite = 'write' . TBase::$tmethod[$etype];
+        } else {
+            $espec = $spec['elem'];
+        }
+        if ($set) {
+            $xfer += $output->writeSetBegin($etype, count($var));
+        } else {
+            $xfer += $output->writeListBegin($etype, count($var));
+        }
+        foreach ($var as $key => $val) {
+            $elem = $set ? $key : $val;
+            if (isset($ewrite)) {
+                $xfer += $output->$ewrite($elem);
+            } else {
+                switch ($etype) {
+                    case TType::STRUCT:
+                        $xfer += $elem->write($output);
+                        break;
+                    case TType::MAP:
+                        $xfer += $this->_writeMap($elem, $espec, $output);
+                        break;
+                    case TType::LST:
+                        $xfer += $this->_writeList($elem, $espec, $output, false);
+                        break;
+                    case TType::SET:
+                        $xfer += $this->_writeList($elem, $espec, $output, true);
+                        break;
+                }
+            }
+        }
+        if ($set) {
+            $xfer += $output->writeSetEnd();
+        } else {
+            $xfer += $output->writeListEnd();
+        }
+
+        return $xfer;
+    }
+
+    protected function _write($class, $spec, $output)
+    {
+        $xfer = 0;
+        $xfer += $output->writeStructBegin($class);
+        foreach ($spec as $fid => $fspec) {
+            $var = $fspec['var'];
+            if ($this->$var !== null) {
+                $ftype = $fspec['type'];
+                $xfer += $output->writeFieldBegin($var, $ftype, $fid);
+                if (isset(TBase::$tmethod[$ftype])) {
+                    $func = 'write' . TBase::$tmethod[$ftype];
+                    $xfer += $output->$func($this->$var);
+                } else {
+                    switch ($ftype) {
+                        case TType::STRUCT:
+                            $xfer += $this->$var->write($output);
+                            break;
+                        case TType::MAP:
+                            $xfer += $this->_writeMap($this->$var, $fspec, $output);
+                            break;
+                        case TType::LST:
+                            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
+                            break;
+                        case TType::SET:
+                            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
+                            break;
+                    }
+                }
+                $xfer += $output->writeFieldEnd();
+            }
+        }
+        $xfer += $output->writeFieldStop();
+        $xfer += $output->writeStructEnd();
+
+        return $xfer;
+    }
+}
diff --git a/lib/php/lib/Thrift/Exception/TProtocolException.php b/lib/php/lib/Exception/TProtocolException.php
similarity index 78%
rename from lib/php/lib/Thrift/Exception/TProtocolException.php
rename to lib/php/lib/Exception/TProtocolException.php
index ba7135c..3a55d45 100644
--- a/lib/php/lib/Thrift/Exception/TProtocolException.php
+++ b/lib/php/lib/Exception/TProtocolException.php
@@ -35,16 +35,16 @@
  */
 class TProtocolException extends TException
 {
-  const UNKNOWN = 0;
-  const INVALID_DATA = 1;
-  const NEGATIVE_SIZE = 2;
-  const SIZE_LIMIT = 3;
-  const BAD_VERSION = 4;
-  const NOT_IMPLEMENTED = 5;
-  const DEPTH_LIMIT = 6;
+    const UNKNOWN = 0;
+    const INVALID_DATA = 1;
+    const NEGATIVE_SIZE = 2;
+    const SIZE_LIMIT = 3;
+    const BAD_VERSION = 4;
+    const NOT_IMPLEMENTED = 5;
+    const DEPTH_LIMIT = 6;
 
-  public function __construct($message=null, $code=0)
-  {
-    parent::__construct($message, $code);
-  }
+    public function __construct($message = null, $code = 0)
+    {
+        parent::__construct($message, $code);
+    }
 }
diff --git a/lib/php/lib/Thrift/Exception/TTransportException.php b/lib/php/lib/Exception/TTransportException.php
similarity index 79%
rename from lib/php/lib/Thrift/Exception/TTransportException.php
rename to lib/php/lib/Exception/TTransportException.php
index 0074467..7d8d567 100644
--- a/lib/php/lib/Thrift/Exception/TTransportException.php
+++ b/lib/php/lib/Exception/TTransportException.php
@@ -27,14 +27,14 @@
  */
 class TTransportException extends TException
 {
-  const UNKNOWN = 0;
-  const NOT_OPEN = 1;
-  const ALREADY_OPEN = 2;
-  const TIMED_OUT = 3;
-  const END_OF_FILE = 4;
+    const UNKNOWN = 0;
+    const NOT_OPEN = 1;
+    const ALREADY_OPEN = 2;
+    const TIMED_OUT = 3;
+    const END_OF_FILE = 4;
 
-  public function __construct($message=null, $code=0)
-  {
-    parent::__construct($message, $code);
-  }
+    public function __construct($message = null, $code = 0)
+    {
+        parent::__construct($message, $code);
+    }
 }
diff --git a/lib/php/lib/Thrift/Factory/TBinaryProtocolFactory.php b/lib/php/lib/Factory/TBinaryProtocolFactory.php
similarity index 72%
rename from lib/php/lib/Thrift/Factory/TBinaryProtocolFactory.php
rename to lib/php/lib/Factory/TBinaryProtocolFactory.php
index 0c1c4a7..2519183 100644
--- a/lib/php/lib/Thrift/Factory/TBinaryProtocolFactory.php
+++ b/lib/php/lib/Factory/TBinaryProtocolFactory.php
@@ -29,17 +29,17 @@
  */
 class TBinaryProtocolFactory implements TProtocolFactory
 {
-  private $strictRead_ = false;
-  private $strictWrite_ = false;
+    private $strictRead_ = false;
+    private $strictWrite_ = false;
 
-  public function __construct($strictRead=false, $strictWrite=false)
-  {
-    $this->strictRead_ = $strictRead;
-    $this->strictWrite_ = $strictWrite;
-  }
+    public function __construct($strictRead = false, $strictWrite = false)
+    {
+        $this->strictRead_ = $strictRead;
+        $this->strictWrite_ = $strictWrite;
+    }
 
-  public function getProtocol($trans)
-  {
-    return new TBinaryProtocol($trans, $this->strictRead_, $this->strictWrite_);
-  }
+    public function getProtocol($trans)
+    {
+        return new TBinaryProtocol($trans, $this->strictRead_, $this->strictWrite_);
+    }
 }
diff --git a/lib/php/lib/Thrift/Factory/TCompactProtocolFactory.php b/lib/php/lib/Factory/TCompactProtocolFactory.php
similarity index 87%
rename from lib/php/lib/Thrift/Factory/TCompactProtocolFactory.php
rename to lib/php/lib/Factory/TCompactProtocolFactory.php
index f4b4fe3..11fb8ff 100644
--- a/lib/php/lib/Thrift/Factory/TCompactProtocolFactory.php
+++ b/lib/php/lib/Factory/TCompactProtocolFactory.php
@@ -29,12 +29,12 @@
  */
 class TCompactProtocolFactory implements TProtocolFactory
 {
-  public function __construct()
-  {
-  }
+    public function __construct()
+    {
+    }
 
-  public function getProtocol($trans)
-  {
-    return new TCompactProtocol($trans);
-  }
+    public function getProtocol($trans)
+    {
+        return new TCompactProtocol($trans);
+    }
 }
diff --git a/lib/php/lib/Thrift/Factory/TJSONProtocolFactory.php b/lib/php/lib/Factory/TJSONProtocolFactory.php
similarity index 100%
rename from lib/php/lib/Thrift/Factory/TJSONProtocolFactory.php
rename to lib/php/lib/Factory/TJSONProtocolFactory.php
diff --git a/lib/php/lib/Thrift/Factory/TProtocolFactory.php b/lib/php/lib/Factory/TProtocolFactory.php
similarity index 85%
rename from lib/php/lib/Thrift/Factory/TProtocolFactory.php
rename to lib/php/lib/Factory/TProtocolFactory.php
index 4c9562d..d3066c8 100644
--- a/lib/php/lib/Thrift/Factory/TProtocolFactory.php
+++ b/lib/php/lib/Factory/TProtocolFactory.php
@@ -27,10 +27,10 @@
  */
 interface TProtocolFactory
 {
-  /**
-   * Build a protocol from the base transport
-   *
-   * @return Thrift\Protocol\TProtocol protocol
-   */
-  public function getProtocol($trans);
+    /**
+     * Build a protocol from the base transport
+     *
+     * @return Thrift\Protocol\TProtocol protocol
+     */
+    public function getProtocol($trans);
 }
diff --git a/lib/php/lib/Thrift/Factory/TStringFuncFactory.php b/lib/php/lib/Factory/TStringFuncFactory.php
similarity index 83%
rename from lib/php/lib/Thrift/Factory/TStringFuncFactory.php
rename to lib/php/lib/Factory/TStringFuncFactory.php
index 6ad6839..30de4d7 100644
--- a/lib/php/lib/Thrift/Factory/TStringFuncFactory.php
+++ b/lib/php/lib/Factory/TStringFuncFactory.php
@@ -21,8 +21,9 @@
 
 namespace Thrift\Factory;
 
-use Thrift\StringFunc\Mbstring;
 use Thrift\StringFunc\Core;
+use Thrift\StringFunc\Mbstring;
+use Thrift\StringFunc\TStringFunc;
 
 class TStringFuncFactory
 {
@@ -49,17 +50,16 @@
          * Cannot use str* functions for byte counting because multibyte
          * characters will be read a single bytes.
          *
-         * See: http://us.php.net/manual/en/mbstring.overload.php
+         * See: http://php.net/manual/en/mbstring.overload.php
          */
         if (ini_get('mbstring.func_overload') & 2) {
             self::$_instance = new Mbstring();
-        }
-        /**
-         * mbstring is not installed or does not have function overloading
-         * of the str* functions enabled so use PHP core str* functions for
-         * byte counting.
-         */
-        else {
+        } else {
+            /**
+             * mbstring is not installed or does not have function overloading
+             * of the str* functions enabled so use PHP core str* functions for
+             * byte counting.
+             */
             self::$_instance = new Core();
         }
     }
diff --git a/lib/php/lib/Factory/TTransportFactory.php b/lib/php/lib/Factory/TTransportFactory.php
new file mode 100644
index 0000000..43f2eec
--- /dev/null
+++ b/lib/php/lib/Factory/TTransportFactory.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Thrift\Factory;
+
+use Thrift\Transport\TTransport;
+
+class TTransportFactory
+{
+    /**
+     * @static
+     * @param TTransport $transport
+     * @return TTransport
+     */
+    public static function getTransport(TTransport $transport)
+    {
+        return $transport;
+    }
+}
diff --git a/lib/php/lib/Thrift/Protocol/JSON/BaseContext.php b/lib/php/lib/Protocol/JSON/BaseContext.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/JSON/BaseContext.php
rename to lib/php/lib/Protocol/JSON/BaseContext.php
diff --git a/lib/php/lib/Thrift/Protocol/JSON/ListContext.php b/lib/php/lib/Protocol/JSON/ListContext.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/JSON/ListContext.php
rename to lib/php/lib/Protocol/JSON/ListContext.php
diff --git a/lib/php/lib/Thrift/Protocol/JSON/LookaheadReader.php b/lib/php/lib/Protocol/JSON/LookaheadReader.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/JSON/LookaheadReader.php
rename to lib/php/lib/Protocol/JSON/LookaheadReader.php
diff --git a/lib/php/lib/Thrift/Protocol/JSON/PairContext.php b/lib/php/lib/Protocol/JSON/PairContext.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/JSON/PairContext.php
rename to lib/php/lib/Protocol/JSON/PairContext.php
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php b/lib/php/lib/Protocol/SimpleJSON/CollectionMapKeyException.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php
rename to lib/php/lib/Protocol/SimpleJSON/CollectionMapKeyException.php
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php b/lib/php/lib/Protocol/SimpleJSON/Context.php
similarity index 99%
rename from lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php
rename to lib/php/lib/Protocol/SimpleJSON/Context.php
index dcffbcb..dbd16fa 100644
--- a/lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php
+++ b/lib/php/lib/Protocol/SimpleJSON/Context.php
@@ -33,4 +33,3 @@
         return false;
     }
 }
-
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/ListContext.php b/lib/php/lib/Protocol/SimpleJSON/ListContext.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/SimpleJSON/ListContext.php
rename to lib/php/lib/Protocol/SimpleJSON/ListContext.php
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/MapContext.php b/lib/php/lib/Protocol/SimpleJSON/MapContext.php
similarity index 96%
rename from lib/php/lib/Thrift/Protocol/SimpleJSON/MapContext.php
rename to lib/php/lib/Protocol/SimpleJSON/MapContext.php
index bb9a04d..61c060d 100644
--- a/lib/php/lib/Thrift/Protocol/SimpleJSON/MapContext.php
+++ b/lib/php/lib/Protocol/SimpleJSON/MapContext.php
@@ -22,8 +22,6 @@
 
 namespace Thrift\Protocol\SimpleJSON;
 
-use Thrift\Protocol\TSimpleJSONProtocol;
-
 class MapContext extends StructContext
 {
     protected $isKey = true;
@@ -47,5 +45,3 @@
         return $this->isKey;
     }
 }
-
-
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/StructContext.php b/lib/php/lib/Protocol/SimpleJSON/StructContext.php
similarity index 93%
rename from lib/php/lib/Thrift/Protocol/SimpleJSON/StructContext.php
rename to lib/php/lib/Protocol/SimpleJSON/StructContext.php
index 8162f2b..38a62d1 100644
--- a/lib/php/lib/Thrift/Protocol/SimpleJSON/StructContext.php
+++ b/lib/php/lib/Protocol/SimpleJSON/StructContext.php
@@ -43,11 +43,10 @@
         } else {
             $this->p_->getTransport()->write(
                 $this->colon_ ?
-                TSimpleJSONProtocol::COLON :
-                TSimpleJSONProtocol::COMMA
+                    TSimpleJSONProtocol::COLON :
+                    TSimpleJSONProtocol::COMMA
             );
             $this->colon_ = !$this->colon_;
         }
     }
 }
-
diff --git a/lib/php/lib/Protocol/TBinaryProtocol.php b/lib/php/lib/Protocol/TBinaryProtocol.php
new file mode 100644
index 0000000..cda5c0d
--- /dev/null
+++ b/lib/php/lib/Protocol/TBinaryProtocol.php
@@ -0,0 +1,453 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Binary implementation of the Thrift protocol.
+ *
+ */
+class TBinaryProtocol extends TProtocol
+{
+    const VERSION_MASK = 0xffff0000;
+    const VERSION_1 = 0x80010000;
+
+    protected $strictRead_ = false;
+    protected $strictWrite_ = true;
+
+    public function __construct($trans, $strictRead = false, $strictWrite = true)
+    {
+        parent::__construct($trans);
+        $this->strictRead_ = $strictRead;
+        $this->strictWrite_ = $strictWrite;
+    }
+
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        if ($this->strictWrite_) {
+            $version = self::VERSION_1 | $type;
+
+            return
+                $this->writeI32($version) +
+                $this->writeString($name) +
+                $this->writeI32($seqid);
+        } else {
+            return
+                $this->writeString($name) +
+                $this->writeByte($type) +
+                $this->writeI32($seqid);
+        }
+    }
+
+    public function writeMessageEnd()
+    {
+        return 0;
+    }
+
+    public function writeStructBegin($name)
+    {
+        return 0;
+    }
+
+    public function writeStructEnd()
+    {
+        return 0;
+    }
+
+    public function writeFieldBegin($fieldName, $fieldType, $fieldId)
+    {
+        return
+            $this->writeByte($fieldType) +
+            $this->writeI16($fieldId);
+    }
+
+    public function writeFieldEnd()
+    {
+        return 0;
+    }
+
+    public function writeFieldStop()
+    {
+        return
+            $this->writeByte(TType::STOP);
+    }
+
+    public function writeMapBegin($keyType, $valType, $size)
+    {
+        return
+            $this->writeByte($keyType) +
+            $this->writeByte($valType) +
+            $this->writeI32($size);
+    }
+
+    public function writeMapEnd()
+    {
+        return 0;
+    }
+
+    public function writeListBegin($elemType, $size)
+    {
+        return
+            $this->writeByte($elemType) +
+            $this->writeI32($size);
+    }
+
+    public function writeListEnd()
+    {
+        return 0;
+    }
+
+    public function writeSetBegin($elemType, $size)
+    {
+        return
+            $this->writeByte($elemType) +
+            $this->writeI32($size);
+    }
+
+    public function writeSetEnd()
+    {
+        return 0;
+    }
+
+    public function writeBool($value)
+    {
+        $data = pack('c', $value ? 1 : 0);
+        $this->trans_->write($data, 1);
+
+        return 1;
+    }
+
+    public function writeByte($value)
+    {
+        $data = pack('c', $value);
+        $this->trans_->write($data, 1);
+
+        return 1;
+    }
+
+    public function writeI16($value)
+    {
+        $data = pack('n', $value);
+        $this->trans_->write($data, 2);
+
+        return 2;
+    }
+
+    public function writeI32($value)
+    {
+        $data = pack('N', $value);
+        $this->trans_->write($data, 4);
+
+        return 4;
+    }
+
+    public function writeI64($value)
+    {
+        // If we are on a 32bit architecture we have to explicitly deal with
+        // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+        // as signed and any int over 2^31 - 1 as a float
+        if (PHP_INT_SIZE == 4) {
+            $neg = $value < 0;
+
+            if ($neg) {
+                $value *= -1;
+            }
+
+            $hi = (int)($value / 4294967296);
+            $lo = (int)$value;
+
+            if ($neg) {
+                $hi = ~$hi;
+                $lo = ~$lo;
+                if (($lo & (int)0xffffffff) == (int)0xffffffff) {
+                    $lo = 0;
+                    $hi++;
+                } else {
+                    $lo++;
+                }
+            }
+            $data = pack('N2', $hi, $lo);
+        } else {
+            $hi = $value >> 32;
+            $lo = $value & 0xFFFFFFFF;
+            $data = pack('N2', $hi, $lo);
+        }
+
+        $this->trans_->write($data, 8);
+
+        return 8;
+    }
+
+    public function writeDouble($value)
+    {
+        $data = pack('d', $value);
+        $this->trans_->write(strrev($data), 8);
+
+        return 8;
+    }
+
+    public function writeString($value)
+    {
+        $len = TStringFuncFactory::create()->strlen($value);
+        $result = $this->writeI32($len);
+        if ($len) {
+            $this->trans_->write($value, $len);
+        }
+
+        return $result + $len;
+    }
+
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        $result = $this->readI32($sz);
+        if ($sz < 0) {
+            $version = (int)($sz & self::VERSION_MASK);
+            if ($version != (int)self::VERSION_1) {
+                throw new TProtocolException('Bad version identifier: ' . $sz, TProtocolException::BAD_VERSION);
+            }
+            $type = $sz & 0x000000ff;
+            $result +=
+                $this->readString($name) +
+                $this->readI32($seqid);
+        } else {
+            if ($this->strictRead_) {
+                throw new TProtocolException(
+                    'No version identifier, old protocol client?',
+                    TProtocolException::BAD_VERSION
+                );
+            } else {
+                // Handle pre-versioned input
+                $name = $this->trans_->readAll($sz);
+                $result +=
+                    $sz +
+                    $this->readByte($type) +
+                    $this->readI32($seqid);
+            }
+        }
+
+        return $result;
+    }
+
+    public function readMessageEnd()
+    {
+        return 0;
+    }
+
+    public function readStructBegin(&$name)
+    {
+        $name = '';
+
+        return 0;
+    }
+
+    public function readStructEnd()
+    {
+        return 0;
+    }
+
+    public function readFieldBegin(&$name, &$fieldType, &$fieldId)
+    {
+        $result = $this->readByte($fieldType);
+        if ($fieldType == TType::STOP) {
+            $fieldId = 0;
+
+            return $result;
+        }
+        $result += $this->readI16($fieldId);
+
+        return $result;
+    }
+
+    public function readFieldEnd()
+    {
+        return 0;
+    }
+
+    public function readMapBegin(&$keyType, &$valType, &$size)
+    {
+        return
+            $this->readByte($keyType) +
+            $this->readByte($valType) +
+            $this->readI32($size);
+    }
+
+    public function readMapEnd()
+    {
+        return 0;
+    }
+
+    public function readListBegin(&$elemType, &$size)
+    {
+        return
+            $this->readByte($elemType) +
+            $this->readI32($size);
+    }
+
+    public function readListEnd()
+    {
+        return 0;
+    }
+
+    public function readSetBegin(&$elemType, &$size)
+    {
+        return
+            $this->readByte($elemType) +
+            $this->readI32($size);
+    }
+
+    public function readSetEnd()
+    {
+        return 0;
+    }
+
+    public function readBool(&$value)
+    {
+        $data = $this->trans_->readAll(1);
+        $arr = unpack('c', $data);
+        $value = $arr[1] == 1;
+
+        return 1;
+    }
+
+    public function readByte(&$value)
+    {
+        $data = $this->trans_->readAll(1);
+        $arr = unpack('c', $data);
+        $value = $arr[1];
+
+        return 1;
+    }
+
+    public function readI16(&$value)
+    {
+        $data = $this->trans_->readAll(2);
+        $arr = unpack('n', $data);
+        $value = $arr[1];
+        if ($value > 0x7fff) {
+            $value = 0 - (($value - 1) ^ 0xffff);
+        }
+
+        return 2;
+    }
+
+    public function readI32(&$value)
+    {
+        $data = $this->trans_->readAll(4);
+        $arr = unpack('N', $data);
+        $value = $arr[1];
+        if ($value > 0x7fffffff) {
+            $value = 0 - (($value - 1) ^ 0xffffffff);
+        }
+
+        return 4;
+    }
+
+    public function readI64(&$value)
+    {
+        $data = $this->trans_->readAll(8);
+
+        $arr = unpack('N2', $data);
+
+        // If we are on a 32bit architecture we have to explicitly deal with
+        // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+        // as signed and any int over 2^31 - 1 as a float
+        if (PHP_INT_SIZE == 4) {
+            $hi = $arr[1];
+            $lo = $arr[2];
+            $isNeg = $hi < 0;
+
+            // Check for a negative
+            if ($isNeg) {
+                $hi = ~$hi & (int)0xffffffff;
+                $lo = ~$lo & (int)0xffffffff;
+
+                if ($lo == (int)0xffffffff) {
+                    $hi++;
+                    $lo = 0;
+                } else {
+                    $lo++;
+                }
+            }
+
+            // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
+            // explicitly below
+
+            if ($hi & (int)0x80000000) {
+                $hi &= (int)0x7fffffff;
+                $hi += 0x80000000;
+            }
+
+            if ($lo & (int)0x80000000) {
+                $lo &= (int)0x7fffffff;
+                $lo += 0x80000000;
+            }
+
+            $value = $hi * 4294967296 + $lo;
+
+            if ($isNeg) {
+                $value = 0 - $value;
+            }
+        } else {
+            // Upcast negatives in LSB bit
+            if ($arr[2] & 0x80000000) {
+                $arr[2] = $arr[2] & 0xffffffff;
+            }
+
+            // Check for a negative
+            if ($arr[1] & 0x80000000) {
+                $arr[1] = $arr[1] & 0xffffffff;
+                $arr[1] = $arr[1] ^ 0xffffffff;
+                $arr[2] = $arr[2] ^ 0xffffffff;
+                $value = 0 - $arr[1] * 4294967296 - $arr[2] - 1;
+            } else {
+                $value = $arr[1] * 4294967296 + $arr[2];
+            }
+        }
+
+        return 8;
+    }
+
+    public function readDouble(&$value)
+    {
+        $data = strrev($this->trans_->readAll(8));
+        $arr = unpack('d', $data);
+        $value = $arr[1];
+
+        return 8;
+    }
+
+    public function readString(&$value)
+    {
+        $result = $this->readI32($len);
+        if ($len) {
+            $value = $this->trans_->readAll($len);
+        } else {
+            $value = '';
+        }
+
+        return $result + $len;
+    }
+}
diff --git a/lib/php/lib/Protocol/TBinaryProtocolAccelerated.php b/lib/php/lib/Protocol/TBinaryProtocolAccelerated.php
new file mode 100644
index 0000000..ff799a6
--- /dev/null
+++ b/lib/php/lib/Protocol/TBinaryProtocolAccelerated.php
@@ -0,0 +1,67 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Transport\TBufferedTransport;
+
+/**
+ * Accelerated binary protocol: used in conjunction with the thrift_protocol
+ * extension for faster deserialization
+ */
+class TBinaryProtocolAccelerated extends TBinaryProtocol
+{
+    public function __construct($trans, $strictRead = false, $strictWrite = true)
+    {
+        // If the transport doesn't implement putBack, wrap it in a
+        // TBufferedTransport (which does)
+
+        // NOTE (t.heintz): This is very evil to do, because the TBufferedTransport may swallow bytes, which
+        // are then never written to the underlying transport. This happens precisely when a number of bytes
+        // less than the max buffer size (512 by default) is written to the transport and then flush() is NOT
+        // called. In that case the data stays in the writeBuffer of the transport, from where it can never be
+        // accessed again (for example through read()).
+        //
+        // Since the caller of this method does not know about the wrapping transport, this creates bugs which
+        // are very difficult to find. Hence the wrapping of a transport in a buffer should be left to the
+        // calling code. An interface could used to mandate the presence of the putBack() method in the transport.
+        //
+        // I am leaving this code in nonetheless, because there may be applications depending on this behavior.
+        //
+        // @see THRIFT-1579
+
+        if (!method_exists($trans, 'putBack')) {
+            $trans = new TBufferedTransport($trans);
+        }
+        parent::__construct($trans, $strictRead, $strictWrite);
+    }
+
+    public function isStrictRead()
+    {
+        return $this->strictRead_;
+    }
+
+    public function isStrictWrite()
+    {
+        return $this->strictWrite_;
+    }
+}
diff --git a/lib/php/lib/Protocol/TCompactProtocol.php b/lib/php/lib/Protocol/TCompactProtocol.php
new file mode 100644
index 0000000..1af2a27
--- /dev/null
+++ b/lib/php/lib/Protocol/TCompactProtocol.php
@@ -0,0 +1,739 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Compact implementation of the Thrift protocol.
+ *
+ */
+class TCompactProtocol extends TProtocol
+{
+    const COMPACT_STOP = 0x00;
+    const COMPACT_TRUE = 0x01;
+    const COMPACT_FALSE = 0x02;
+    const COMPACT_BYTE = 0x03;
+    const COMPACT_I16 = 0x04;
+    const COMPACT_I32 = 0x05;
+    const COMPACT_I64 = 0x06;
+    const COMPACT_DOUBLE = 0x07;
+    const COMPACT_BINARY = 0x08;
+    const COMPACT_LIST = 0x09;
+    const COMPACT_SET = 0x0A;
+    const COMPACT_MAP = 0x0B;
+    const COMPACT_STRUCT = 0x0C;
+
+    const STATE_CLEAR = 0;
+    const STATE_FIELD_WRITE = 1;
+    const STATE_VALUE_WRITE = 2;
+    const STATE_CONTAINER_WRITE = 3;
+    const STATE_BOOL_WRITE = 4;
+    const STATE_FIELD_READ = 5;
+    const STATE_CONTAINER_READ = 6;
+    const STATE_VALUE_READ = 7;
+    const STATE_BOOL_READ = 8;
+
+    const VERSION_MASK = 0x1f;
+    const VERSION = 1;
+    const PROTOCOL_ID = 0x82;
+    const TYPE_MASK = 0xe0;
+    const TYPE_BITS = 0x07;
+    const TYPE_SHIFT_AMOUNT = 5;
+
+    protected static $ctypes = array(
+        TType::STOP => TCompactProtocol::COMPACT_STOP,
+        TType::BOOL => TCompactProtocol::COMPACT_TRUE, // used for collection
+        TType::BYTE => TCompactProtocol::COMPACT_BYTE,
+        TType::I16 => TCompactProtocol::COMPACT_I16,
+        TType::I32 => TCompactProtocol::COMPACT_I32,
+        TType::I64 => TCompactProtocol::COMPACT_I64,
+        TType::DOUBLE => TCompactProtocol::COMPACT_DOUBLE,
+        TType::STRING => TCompactProtocol::COMPACT_BINARY,
+        TType::STRUCT => TCompactProtocol::COMPACT_STRUCT,
+        TType::LST => TCompactProtocol::COMPACT_LIST,
+        TType::SET => TCompactProtocol::COMPACT_SET,
+        TType::MAP => TCompactProtocol::COMPACT_MAP,
+    );
+
+    protected static $ttypes = array(
+        TCompactProtocol::COMPACT_STOP => TType::STOP,
+        TCompactProtocol::COMPACT_TRUE => TType::BOOL, // used for collection
+        TCompactProtocol::COMPACT_FALSE => TType::BOOL,
+        TCompactProtocol::COMPACT_BYTE => TType::BYTE,
+        TCompactProtocol::COMPACT_I16 => TType::I16,
+        TCompactProtocol::COMPACT_I32 => TType::I32,
+        TCompactProtocol::COMPACT_I64 => TType::I64,
+        TCompactProtocol::COMPACT_DOUBLE => TType::DOUBLE,
+        TCompactProtocol::COMPACT_BINARY => TType::STRING,
+        TCompactProtocol::COMPACT_STRUCT => TType::STRUCT,
+        TCompactProtocol::COMPACT_LIST => TType::LST,
+        TCompactProtocol::COMPACT_SET => TType::SET,
+        TCompactProtocol::COMPACT_MAP => TType::MAP,
+    );
+
+    protected $state = TCompactProtocol::STATE_CLEAR;
+    protected $lastFid = 0;
+    protected $boolFid = null;
+    protected $boolValue = null;
+    protected $structs = array();
+    protected $containers = array();
+
+    // Some varint / zigzag helper methods
+    public function toZigZag($n, $bits)
+    {
+        return ($n << 1) ^ ($n >> ($bits - 1));
+    }
+
+    public function fromZigZag($n)
+    {
+        return ($n >> 1) ^ -($n & 1);
+    }
+
+    public function getVarint($data)
+    {
+        $out = "";
+        while (true) {
+            if (($data & ~0x7f) === 0) {
+                $out .= chr($data);
+                break;
+            } else {
+                $out .= chr(($data & 0xff) | 0x80);
+                $data = $data >> 7;
+            }
+        }
+
+        return $out;
+    }
+
+    public function writeVarint($data)
+    {
+        $out = $this->getVarint($data);
+        $result = TStringFuncFactory::create()->strlen($out);
+        $this->trans_->write($out, $result);
+
+        return $result;
+    }
+
+    public function readVarint(&$result)
+    {
+        $idx = 0;
+        $shift = 0;
+        $result = 0;
+        while (true) {
+            $x = $this->trans_->readAll(1);
+            $arr = unpack('C', $x);
+            $byte = $arr[1];
+            $idx += 1;
+            $result |= ($byte & 0x7f) << $shift;
+            if (($byte >> 7) === 0) {
+                return $idx;
+            }
+            $shift += 7;
+        }
+
+        return $idx;
+    }
+
+    public function __construct($trans)
+    {
+        parent::__construct($trans);
+    }
+
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        $written =
+            $this->writeUByte(TCompactProtocol::PROTOCOL_ID) +
+            $this->writeUByte(TCompactProtocol::VERSION |
+                ($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)) +
+            $this->writeVarint($seqid) +
+            $this->writeString($name);
+        $this->state = TCompactProtocol::STATE_VALUE_WRITE;
+
+        return $written;
+    }
+
+    public function writeMessageEnd()
+    {
+        $this->state = TCompactProtocol::STATE_CLEAR;
+
+        return 0;
+    }
+
+    public function writeStructBegin($name)
+    {
+        $this->structs[] = array($this->state, $this->lastFid);
+        $this->state = TCompactProtocol::STATE_FIELD_WRITE;
+        $this->lastFid = 0;
+
+        return 0;
+    }
+
+    public function writeStructEnd()
+    {
+        $old_values = array_pop($this->structs);
+        $this->state = $old_values[0];
+        $this->lastFid = $old_values[1];
+
+        return 0;
+    }
+
+    public function writeFieldStop()
+    {
+        return $this->writeByte(0);
+    }
+
+    public function writeFieldHeader($type, $fid)
+    {
+        $written = 0;
+        $delta = $fid - $this->lastFid;
+        if (0 < $delta && $delta <= 15) {
+            $written = $this->writeUByte(($delta << 4) | $type);
+        } else {
+            $written = $this->writeByte($type) +
+                $this->writeI16($fid);
+        }
+        $this->lastFid = $fid;
+
+        return $written;
+    }
+
+    public function writeFieldBegin($field_name, $field_type, $field_id)
+    {
+        if ($field_type == TTYPE::BOOL) {
+            $this->state = TCompactProtocol::STATE_BOOL_WRITE;
+            $this->boolFid = $field_id;
+
+            return 0;
+        } else {
+            $this->state = TCompactProtocol::STATE_VALUE_WRITE;
+
+            return $this->writeFieldHeader(self::$ctypes[$field_type], $field_id);
+        }
+    }
+
+    public function writeFieldEnd()
+    {
+        $this->state = TCompactProtocol::STATE_FIELD_WRITE;
+
+        return 0;
+    }
+
+    public function writeCollectionBegin($etype, $size)
+    {
+        $written = 0;
+        if ($size <= 14) {
+            $written = $this->writeUByte($size << 4 |
+                self::$ctypes[$etype]);
+        } else {
+            $written = $this->writeUByte(0xf0 |
+                    self::$ctypes[$etype]) +
+                $this->writeVarint($size);
+        }
+        $this->containers[] = $this->state;
+        $this->state = TCompactProtocol::STATE_CONTAINER_WRITE;
+
+        return $written;
+    }
+
+    public function writeMapBegin($key_type, $val_type, $size)
+    {
+        $written = 0;
+        if ($size == 0) {
+            $written = $this->writeByte(0);
+        } else {
+            $written = $this->writeVarint($size) +
+                $this->writeUByte(self::$ctypes[$key_type] << 4 |
+                    self::$ctypes[$val_type]);
+        }
+        $this->containers[] = $this->state;
+
+        return $written;
+    }
+
+    public function writeCollectionEnd()
+    {
+        $this->state = array_pop($this->containers);
+
+        return 0;
+    }
+
+    public function writeMapEnd()
+    {
+        return $this->writeCollectionEnd();
+    }
+
+    public function writeListBegin($elem_type, $size)
+    {
+        return $this->writeCollectionBegin($elem_type, $size);
+    }
+
+    public function writeListEnd()
+    {
+        return $this->writeCollectionEnd();
+    }
+
+    public function writeSetBegin($elem_type, $size)
+    {
+        return $this->writeCollectionBegin($elem_type, $size);
+    }
+
+    public function writeSetEnd()
+    {
+        return $this->writeCollectionEnd();
+    }
+
+    public function writeBool($value)
+    {
+        if ($this->state == TCompactProtocol::STATE_BOOL_WRITE) {
+            $ctype = TCompactProtocol::COMPACT_FALSE;
+            if ($value) {
+                $ctype = TCompactProtocol::COMPACT_TRUE;
+            }
+
+            return $this->writeFieldHeader($ctype, $this->boolFid);
+        } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_WRITE) {
+            return $this->writeByte($value ? 1 : 0);
+        } else {
+            throw new TProtocolException('Invalid state in compact protocol');
+        }
+    }
+
+    public function writeByte($value)
+    {
+        $data = pack('c', $value);
+        $this->trans_->write($data, 1);
+
+        return 1;
+    }
+
+    public function writeUByte($byte)
+    {
+        $this->trans_->write(pack('C', $byte), 1);
+
+        return 1;
+    }
+
+    public function writeI16($value)
+    {
+        $thing = $this->toZigZag($value, 16);
+
+        return $this->writeVarint($thing);
+    }
+
+    public function writeI32($value)
+    {
+        $thing = $this->toZigZag($value, 32);
+
+        return $this->writeVarint($thing);
+    }
+
+    public function writeDouble($value)
+    {
+        $data = pack('d', $value);
+        $this->trans_->write($data, 8);
+
+        return 8;
+    }
+
+    public function writeString($value)
+    {
+        $len = TStringFuncFactory::create()->strlen($value);
+        $result = $this->writeVarint($len);
+        if ($len) {
+            $this->trans_->write($value, $len);
+        }
+
+        return $result + $len;
+    }
+
+    public function readFieldBegin(&$name, &$field_type, &$field_id)
+    {
+        $result = $this->readUByte($compact_type_and_delta);
+
+        $compact_type = $compact_type_and_delta & 0x0f;
+
+        if ($compact_type == TType::STOP) {
+            $field_type = $compact_type;
+            $field_id = 0;
+
+            return $result;
+        }
+        $delta = $compact_type_and_delta >> 4;
+        if ($delta == 0) {
+            $result += $this->readI16($field_id);
+        } else {
+            $field_id = $this->lastFid + $delta;
+        }
+        $this->lastFid = $field_id;
+        $field_type = $this->getTType($compact_type);
+
+        if ($compact_type == TCompactProtocol::COMPACT_TRUE) {
+            $this->state = TCompactProtocol::STATE_BOOL_READ;
+            $this->boolValue = true;
+        } elseif ($compact_type == TCompactProtocol::COMPACT_FALSE) {
+            $this->state = TCompactProtocol::STATE_BOOL_READ;
+            $this->boolValue = false;
+        } else {
+            $this->state = TCompactProtocol::STATE_VALUE_READ;
+        }
+
+        return $result;
+    }
+
+    public function readFieldEnd()
+    {
+        $this->state = TCompactProtocol::STATE_FIELD_READ;
+
+        return 0;
+    }
+
+    public function readUByte(&$value)
+    {
+        $data = $this->trans_->readAll(1);
+        $arr = unpack('C', $data);
+        $value = $arr[1];
+
+        return 1;
+    }
+
+    public function readByte(&$value)
+    {
+        $data = $this->trans_->readAll(1);
+        $arr = unpack('c', $data);
+        $value = $arr[1];
+
+        return 1;
+    }
+
+    public function readZigZag(&$value)
+    {
+        $result = $this->readVarint($value);
+        $value = $this->fromZigZag($value);
+
+        return $result;
+    }
+
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        $protoId = 0;
+        $result = $this->readUByte($protoId);
+        if ($protoId != TCompactProtocol::PROTOCOL_ID) {
+            throw new TProtocolException('Bad protocol id in TCompact message');
+        }
+        $verType = 0;
+        $result += $this->readUByte($verType);
+        $type = ($verType >> TCompactProtocol::TYPE_SHIFT_AMOUNT) & TCompactProtocol::TYPE_BITS;
+        $version = $verType & TCompactProtocol::VERSION_MASK;
+        if ($version != TCompactProtocol::VERSION) {
+            throw new TProtocolException('Bad version in TCompact message');
+        }
+        $result += $this->readVarint($seqid);
+        $result += $this->readString($name);
+
+        return $result;
+    }
+
+    public function readMessageEnd()
+    {
+        return 0;
+    }
+
+    public function readStructBegin(&$name)
+    {
+        $name = ''; // unused
+        $this->structs[] = array($this->state, $this->lastFid);
+        $this->state = TCompactProtocol::STATE_FIELD_READ;
+        $this->lastFid = 0;
+
+        return 0;
+    }
+
+    public function readStructEnd()
+    {
+        $last = array_pop($this->structs);
+        $this->state = $last[0];
+        $this->lastFid = $last[1];
+
+        return 0;
+    }
+
+    public function readCollectionBegin(&$type, &$size)
+    {
+        $sizeType = 0;
+        $result = $this->readUByte($sizeType);
+        $size = $sizeType >> 4;
+        $type = $this->getTType($sizeType);
+        if ($size == 15) {
+            $result += $this->readVarint($size);
+        }
+        $this->containers[] = $this->state;
+        $this->state = TCompactProtocol::STATE_CONTAINER_READ;
+
+        return $result;
+    }
+
+    public function readMapBegin(&$key_type, &$val_type, &$size)
+    {
+        $result = $this->readVarint($size);
+        $types = 0;
+        if ($size > 0) {
+            $result += $this->readUByte($types);
+        }
+        $val_type = $this->getTType($types);
+        $key_type = $this->getTType($types >> 4);
+        $this->containers[] = $this->state;
+        $this->state = TCompactProtocol::STATE_CONTAINER_READ;
+
+        return $result;
+    }
+
+    public function readCollectionEnd()
+    {
+        $this->state = array_pop($this->containers);
+
+        return 0;
+    }
+
+    public function readMapEnd()
+    {
+        return $this->readCollectionEnd();
+    }
+
+    public function readListBegin(&$elem_type, &$size)
+    {
+        return $this->readCollectionBegin($elem_type, $size);
+    }
+
+    public function readListEnd()
+    {
+        return $this->readCollectionEnd();
+    }
+
+    public function readSetBegin(&$elem_type, &$size)
+    {
+        return $this->readCollectionBegin($elem_type, $size);
+    }
+
+    public function readSetEnd()
+    {
+        return $this->readCollectionEnd();
+    }
+
+    public function readBool(&$value)
+    {
+        if ($this->state == TCompactProtocol::STATE_BOOL_READ) {
+            $value = $this->boolValue;
+
+            return 0;
+        } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_READ) {
+            return $this->readByte($value);
+        } else {
+            throw new TProtocolException('Invalid state in compact protocol');
+        }
+    }
+
+    public function readI16(&$value)
+    {
+        return $this->readZigZag($value);
+    }
+
+    public function readI32(&$value)
+    {
+        return $this->readZigZag($value);
+    }
+
+    public function readDouble(&$value)
+    {
+        $data = $this->trans_->readAll(8);
+        $arr = unpack('d', $data);
+        $value = $arr[1];
+
+        return 8;
+    }
+
+    public function readString(&$value)
+    {
+        $result = $this->readVarint($len);
+        if ($len) {
+            $value = $this->trans_->readAll($len);
+        } else {
+            $value = '';
+        }
+
+        return $result + $len;
+    }
+
+    public function getTType($byte)
+    {
+        return self::$ttypes[$byte & 0x0f];
+    }
+
+    // If we are on a 32bit architecture we have to explicitly deal with
+    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+    // as signed and any int over 2^31 - 1 as a float
+
+    // Read and write I64 as two 32 bit numbers $hi and $lo
+
+    public function readI64(&$value)
+    {
+        // Read varint from wire
+        $hi = 0;
+        $lo = 0;
+
+        $idx = 0;
+        $shift = 0;
+
+        while (true) {
+            $x = $this->trans_->readAll(1);
+            $arr = unpack('C', $x);
+            $byte = $arr[1];
+            $idx += 1;
+            // Shift hi and lo together.
+            if ($shift < 28) {
+                $lo |= (($byte & 0x7f) << $shift);
+            } elseif ($shift == 28) {
+                $lo |= (($byte & 0x0f) << 28);
+                $hi |= (($byte & 0x70) >> 4);
+            } else {
+                $hi |= (($byte & 0x7f) << ($shift - 32));
+            }
+            if (($byte >> 7) === 0) {
+                break;
+            }
+            $shift += 7;
+        }
+
+        // Now, unzig it.
+        $xorer = 0;
+        if ($lo & 1) {
+            $xorer = 0xffffffff;
+        }
+        $lo = ($lo >> 1) & 0x7fffffff;
+        $lo = $lo | (($hi & 1) << 31);
+        $hi = ($hi >> 1) ^ $xorer;
+        $lo = $lo ^ $xorer;
+
+        // Now put $hi and $lo back together
+        $isNeg = $hi < 0 || $hi & 0x80000000;
+
+        // Check for a negative
+        if ($isNeg) {
+            $hi = ~$hi & (int)0xffffffff;
+            $lo = ~$lo & (int)0xffffffff;
+
+            if ($lo == (int)0xffffffff) {
+                $hi++;
+                $lo = 0;
+            } else {
+                $lo++;
+            }
+        }
+
+        // Force 32bit words in excess of 2G to be positive - we deal with sign
+        // explicitly below
+
+        if ($hi & (int)0x80000000) {
+            $hi &= (int)0x7fffffff;
+            $hi += 0x80000000;
+        }
+
+        if ($lo & (int)0x80000000) {
+            $lo &= (int)0x7fffffff;
+            $lo += 0x80000000;
+        }
+
+        // Create as negative value first, since we can store -2^63 but not 2^63
+        $value = -$hi * 4294967296 - $lo;
+
+        if (!$isNeg) {
+            $value = -$value;
+        }
+
+        return $idx;
+    }
+
+    public function writeI64($value)
+    {
+        // If we are in an I32 range, use the easy method below.
+        if (($value > 4294967296) || ($value < -4294967296)) {
+            // Convert $value to $hi and $lo
+            $neg = $value < 0;
+
+            if ($neg) {
+                $value *= -1;
+            }
+
+            $hi = (int)$value >> 32;
+            $lo = (int)$value & 0xffffffff;
+
+            if ($neg) {
+                $hi = ~$hi;
+                $lo = ~$lo;
+                if (($lo & (int)0xffffffff) == (int)0xffffffff) {
+                    $lo = 0;
+                    $hi++;
+                } else {
+                    $lo++;
+                }
+            }
+
+            // Now do the zigging and zagging.
+            $xorer = 0;
+            if ($neg) {
+                $xorer = 0xffffffff;
+            }
+            $lowbit = ($lo >> 31) & 1;
+            $hi = ($hi << 1) | $lowbit;
+            $lo = ($lo << 1);
+            $lo = ($lo ^ $xorer) & 0xffffffff;
+            $hi = ($hi ^ $xorer) & 0xffffffff;
+
+            // now write out the varint, ensuring we shift both hi and lo
+            $out = "";
+            while (true) {
+                if (($lo & ~0x7f) === 0 &&
+                    $hi === 0) {
+                    $out .= chr($lo);
+                    break;
+                } else {
+                    $out .= chr(($lo & 0xff) | 0x80);
+                    $lo = $lo >> 7;
+                    $lo = $lo | ($hi << 25);
+                    $hi = $hi >> 7;
+                    // Right shift carries sign, but we don't want it to.
+                    $hi = $hi & (127 << 25);
+                }
+            }
+
+            $ret = TStringFuncFactory::create()->strlen($out);
+            $this->trans_->write($out, $ret);
+
+            return $ret;
+        } else {
+            return $this->writeVarint($this->toZigZag($value, 64));
+        }
+    }
+}
diff --git a/lib/php/lib/Thrift/Protocol/TJSONProtocol.php b/lib/php/lib/Protocol/TJSONProtocol.php
similarity index 90%
rename from lib/php/lib/Thrift/Protocol/TJSONProtocol.php
rename to lib/php/lib/Protocol/TJSONProtocol.php
index 6d8e81f..9144884 100644
--- a/lib/php/lib/Thrift/Protocol/TJSONProtocol.php
+++ b/lib/php/lib/Protocol/TJSONProtocol.php
@@ -217,9 +217,9 @@
 
     private function hasJSONUnescapedUnicode()
     {
-        if (PHP_MAJOR_VERSION > 5
-            || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4))
+        if (PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4)) {
             return true;
+        }
 
         return false;
     }
@@ -237,18 +237,24 @@
          * High surrogate: 0xD800 - 0xDBFF
          * Low surrogate: 0xDC00 - 0xDFFF
          */
-        $json = preg_replace_callback('/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i',
+        $json = preg_replace_callback(
+            '/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i',
             function ($matches) {
-                return mb_convert_encoding(pack('H*', $matches[1].$matches[2]), 'UTF-8', 'UTF-16BE');
-            }, $json);
+                return mb_convert_encoding(pack('H*', $matches[1] . $matches[2]), 'UTF-8', 'UTF-16BE');
+            },
+            $json
+        );
 
         /*
          * Unescaped characters within the Basic Multilingual Plane
          */
-        $json = preg_replace_callback('/\\\\u([0-9a-f]{4})/i',
+        $json = preg_replace_callback(
+            '/\\\\u([0-9a-f]{4})/i',
             function ($matches) {
                 return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE');
-            }, $json);
+            },
+            $json
+        );
 
         return $json;
     }
@@ -308,54 +314,54 @@
 
     private function writeJSONObjectStart()
     {
-      $this->context_->write();
-      $this->trans_->write(self::LBRACE);
-      $this->pushContext(new PairContext($this));
+        $this->context_->write();
+        $this->trans_->write(self::LBRACE);
+        $this->pushContext(new PairContext($this));
     }
 
     private function writeJSONObjectEnd()
     {
-      $this->popContext();
-      $this->trans_->write(self::RBRACE);
+        $this->popContext();
+        $this->trans_->write(self::RBRACE);
     }
 
     private function writeJSONArrayStart()
     {
-      $this->context_->write();
-      $this->trans_->write(self::LBRACKET);
-      $this->pushContext(new ListContext($this));
+        $this->context_->write();
+        $this->trans_->write(self::LBRACKET);
+        $this->pushContext(new ListContext($this));
     }
 
     private function writeJSONArrayEnd()
     {
-      $this->popContext();
-      $this->trans_->write(self::RBRACKET);
+        $this->popContext();
+        $this->trans_->write(self::RBRACKET);
     }
 
     private function readJSONString($skipContext)
     {
-      if (!$skipContext) {
-        $this->context_->read();
-      }
-
-      $jsonString = '';
-      $lastChar = null;
-      while (true) {
-        $ch = $this->reader_->read();
-        $jsonString .= $ch;
-        if ($ch == self::QUOTE &&
-          $lastChar !== NULL &&
-            $lastChar !== self::ESCSEQ) {
-          break;
+        if (!$skipContext) {
+            $this->context_->read();
         }
-        if ($ch == self::ESCSEQ && $lastChar == self::ESCSEQ) {
-          $lastChar = self::DOUBLEESC;
-        } else {
-          $lastChar = $ch;
-        }
-      }
 
-      return json_decode($jsonString);
+        $jsonString = '';
+        $lastChar = null;
+        while (true) {
+            $ch = $this->reader_->read();
+            $jsonString .= $ch;
+            if ($ch == self::QUOTE &&
+                $lastChar !== null &&
+                $lastChar !== self::ESCSEQ) {
+                break;
+            }
+            if ($ch == self::ESCSEQ && $lastChar == self::ESCSEQ) {
+                $lastChar = self::DOUBLEESC;
+            } else {
+                $lastChar = $ch;
+            }
+        }
+
+        return json_decode($jsonString);
     }
 
     private function isJSONNumeric($b)
@@ -376,8 +382,8 @@
             case '9':
             case 'E':
             case 'e':
-              return true;
-            }
+                return true;
+        }
 
         return false;
     }
@@ -459,8 +465,10 @@
             } elseif ($arr == "Infinity") {
                 return INF;
             } elseif (!$this->context_->escapeNum()) {
-                throw new TProtocolException("Numeric data unexpectedly quoted " . $arr,
-                                              TProtocolException::INVALID_DATA);
+                throw new TProtocolException(
+                    "Numeric data unexpectedly quoted " . $arr,
+                    TProtocolException::INVALID_DATA
+                );
             }
 
             return floatval($arr);
@@ -514,9 +522,9 @@
     /**
      * Writes the message header
      *
-     * @param string $name  Function name
-     * @param int    $type  message type TMessageType::CALL or TMessageType::REPLY
-     * @param int    $seqid The sequence id of this message
+     * @param string $name Function name
+     * @param int $type message type TMessageType::CALL or TMessageType::REPLY
+     * @param int $seqid The sequence id of this message
      */
     public function writeMessageBegin($name, $type, $seqid)
     {
@@ -538,7 +546,7 @@
     /**
      * Writes a struct header.
      *
-     * @param  string     $name Struct name
+     * @param  string $name Struct name
      * @throws TException on write error
      * @return int        How many bytes written
      */
@@ -652,7 +660,7 @@
      * Reads the message header
      *
      * @param string $name Function name
-     * @param int    $type message type TMessageType::CALL or TMessageType::REPLY
+     * @param int $type message type TMessageType::CALL or TMessageType::REPLY
      * @parem int $seqid The sequence id of this message
      */
     public function readMessageBegin(&$name, &$type, &$seqid)
diff --git a/lib/php/lib/Thrift/Protocol/TMultiplexedProtocol.php b/lib/php/lib/Protocol/TMultiplexedProtocol.php
similarity index 100%
rename from lib/php/lib/Thrift/Protocol/TMultiplexedProtocol.php
rename to lib/php/lib/Protocol/TMultiplexedProtocol.php
diff --git a/lib/php/lib/Protocol/TProtocol.php b/lib/php/lib/Protocol/TProtocol.php
new file mode 100644
index 0000000..81aceb6
--- /dev/null
+++ b/lib/php/lib/Protocol/TProtocol.php
@@ -0,0 +1,350 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+
+/**
+ * Protocol base class module.
+ */
+abstract class TProtocol
+{
+    /**
+     * Underlying transport
+     *
+     * @var TTransport
+     */
+    protected $trans_;
+
+    /**
+     * Constructor
+     */
+    protected function __construct($trans)
+    {
+        $this->trans_ = $trans;
+    }
+
+    /**
+     * Accessor for transport
+     *
+     * @return TTransport
+     */
+    public function getTransport()
+    {
+        return $this->trans_;
+    }
+
+    /**
+     * Writes the message header
+     *
+     * @param string $name Function name
+     * @param int $type message type TMessageType::CALL or TMessageType::REPLY
+     * @param int $seqid The sequence id of this message
+     */
+    abstract public function writeMessageBegin($name, $type, $seqid);
+
+    /**
+     * Close the message
+     */
+    abstract public function writeMessageEnd();
+
+    /**
+     * Writes a struct header.
+     *
+     * @param string $name Struct name
+     * @throws TException on write error
+     * @return int How many bytes written
+     */
+    abstract public function writeStructBegin($name);
+
+    /**
+     * Close a struct.
+     *
+     * @throws TException on write error
+     * @return int How many bytes written
+     */
+    abstract public function writeStructEnd();
+
+    /*
+     * Starts a field.
+     *
+     * @param string     $name Field name
+     * @param int        $type Field type
+     * @param int        $fid  Field id
+     * @throws TException on write error
+     * @return int How many bytes written
+     */
+    abstract public function writeFieldBegin($fieldName, $fieldType, $fieldId);
+
+    abstract public function writeFieldEnd();
+
+    abstract public function writeFieldStop();
+
+    abstract public function writeMapBegin($keyType, $valType, $size);
+
+    abstract public function writeMapEnd();
+
+    abstract public function writeListBegin($elemType, $size);
+
+    abstract public function writeListEnd();
+
+    abstract public function writeSetBegin($elemType, $size);
+
+    abstract public function writeSetEnd();
+
+    abstract public function writeBool($bool);
+
+    abstract public function writeByte($byte);
+
+    abstract public function writeI16($i16);
+
+    abstract public function writeI32($i32);
+
+    abstract public function writeI64($i64);
+
+    abstract public function writeDouble($dub);
+
+    abstract public function writeString($str);
+
+    /**
+     * Reads the message header
+     *
+     * @param string $name Function name
+     * @param int $type message type TMessageType::CALL or TMessageType::REPLY
+     * @parem int $seqid The sequence id of this message
+     */
+    abstract public function readMessageBegin(&$name, &$type, &$seqid);
+
+    /**
+     * Read the close of message
+     */
+    abstract public function readMessageEnd();
+
+    abstract public function readStructBegin(&$name);
+
+    abstract public function readStructEnd();
+
+    abstract public function readFieldBegin(&$name, &$fieldType, &$fieldId);
+
+    abstract public function readFieldEnd();
+
+    abstract public function readMapBegin(&$keyType, &$valType, &$size);
+
+    abstract public function readMapEnd();
+
+    abstract public function readListBegin(&$elemType, &$size);
+
+    abstract public function readListEnd();
+
+    abstract public function readSetBegin(&$elemType, &$size);
+
+    abstract public function readSetEnd();
+
+    abstract public function readBool(&$bool);
+
+    abstract public function readByte(&$byte);
+
+    abstract public function readI16(&$i16);
+
+    abstract public function readI32(&$i32);
+
+    abstract public function readI64(&$i64);
+
+    abstract public function readDouble(&$dub);
+
+    abstract public function readString(&$str);
+
+    /**
+     * The skip function is a utility to parse over unrecognized date without
+     * causing corruption.
+     *
+     * @param TType $type What type is it
+     */
+    public function skip($type)
+    {
+        switch ($type) {
+            case TType::BOOL:
+                return $this->readBool($bool);
+            case TType::BYTE:
+                return $this->readByte($byte);
+            case TType::I16:
+                return $this->readI16($i16);
+            case TType::I32:
+                return $this->readI32($i32);
+            case TType::I64:
+                return $this->readI64($i64);
+            case TType::DOUBLE:
+                return $this->readDouble($dub);
+            case TType::STRING:
+                return $this->readString($str);
+            case TType::STRUCT:
+                $result = $this->readStructBegin($name);
+                while (true) {
+                    $result += $this->readFieldBegin($name, $ftype, $fid);
+                    if ($ftype == TType::STOP) {
+                        break;
+                    }
+                    $result += $this->skip($ftype);
+                    $result += $this->readFieldEnd();
+                }
+                $result += $this->readStructEnd();
+
+                return $result;
+
+            case TType::MAP:
+                $result = $this->readMapBegin($keyType, $valType, $size);
+                for ($i = 0; $i < $size; $i++) {
+                    $result += $this->skip($keyType);
+                    $result += $this->skip($valType);
+                }
+                $result += $this->readMapEnd();
+
+                return $result;
+
+            case TType::SET:
+                $result = $this->readSetBegin($elemType, $size);
+                for ($i = 0; $i < $size; $i++) {
+                    $result += $this->skip($elemType);
+                }
+                $result += $this->readSetEnd();
+
+                return $result;
+
+            case TType::LST:
+                $result = $this->readListBegin($elemType, $size);
+                for ($i = 0; $i < $size; $i++) {
+                    $result += $this->skip($elemType);
+                }
+                $result += $this->readListEnd();
+
+                return $result;
+
+            default:
+                throw new TProtocolException(
+                    'Unknown field type: ' . $type,
+                    TProtocolException::INVALID_DATA
+                );
+        }
+    }
+
+    /**
+     * Utility for skipping binary data
+     *
+     * @param TTransport $itrans TTransport object
+     * @param int $type Field type
+     */
+    public static function skipBinary($itrans, $type)
+    {
+        switch ($type) {
+            case TType::BOOL:
+                return $itrans->readAll(1);
+            case TType::BYTE:
+                return $itrans->readAll(1);
+            case TType::I16:
+                return $itrans->readAll(2);
+            case TType::I32:
+                return $itrans->readAll(4);
+            case TType::I64:
+                return $itrans->readAll(8);
+            case TType::DOUBLE:
+                return $itrans->readAll(8);
+            case TType::STRING:
+                $len = unpack('N', $itrans->readAll(4));
+                $len = $len[1];
+                if ($len > 0x7fffffff) {
+                    $len = 0 - (($len - 1) ^ 0xffffffff);
+                }
+
+                return 4 + $itrans->readAll($len);
+
+            case TType::STRUCT:
+                $result = 0;
+                while (true) {
+                    $ftype = 0;
+                    $fid = 0;
+                    $data = $itrans->readAll(1);
+                    $arr = unpack('c', $data);
+                    $ftype = $arr[1];
+                    if ($ftype == TType::STOP) {
+                        break;
+                    }
+                    // I16 field id
+                    $result += $itrans->readAll(2);
+                    $result += self::skipBinary($itrans, $ftype);
+                }
+
+                return $result;
+
+            case TType::MAP:
+                // Ktype
+                $data = $itrans->readAll(1);
+                $arr = unpack('c', $data);
+                $ktype = $arr[1];
+                // Vtype
+                $data = $itrans->readAll(1);
+                $arr = unpack('c', $data);
+                $vtype = $arr[1];
+                // Size
+                $data = $itrans->readAll(4);
+                $arr = unpack('N', $data);
+                $size = $arr[1];
+                if ($size > 0x7fffffff) {
+                    $size = 0 - (($size - 1) ^ 0xffffffff);
+                }
+                $result = 6;
+                for ($i = 0; $i < $size; $i++) {
+                    $result += self::skipBinary($itrans, $ktype);
+                    $result += self::skipBinary($itrans, $vtype);
+                }
+
+                return $result;
+
+            case TType::SET:
+            case TType::LST:
+                // Vtype
+                $data = $itrans->readAll(1);
+                $arr = unpack('c', $data);
+                $vtype = $arr[1];
+                // Size
+                $data = $itrans->readAll(4);
+                $arr = unpack('N', $data);
+                $size = $arr[1];
+                if ($size > 0x7fffffff) {
+                    $size = 0 - (($size - 1) ^ 0xffffffff);
+                }
+                $result = 5;
+                for ($i = 0; $i < $size; $i++) {
+                    $result += self::skipBinary($itrans, $vtype);
+                }
+
+                return $result;
+
+            default:
+                throw new TProtocolException(
+                    'Unknown field type: ' . $type,
+                    TProtocolException::INVALID_DATA
+                );
+        }
+    }
+}
diff --git a/lib/php/lib/Thrift/Protocol/TProtocolDecorator.php b/lib/php/lib/Protocol/TProtocolDecorator.php
similarity index 99%
rename from lib/php/lib/Thrift/Protocol/TProtocolDecorator.php
rename to lib/php/lib/Protocol/TProtocolDecorator.php
index c08c4d5..a85e0b8 100644
--- a/lib/php/lib/Thrift/Protocol/TProtocolDecorator.php
+++ b/lib/php/lib/Protocol/TProtocolDecorator.php
@@ -21,6 +21,7 @@
  */
 
 namespace Thrift\Protocol;
+
 use Thrift\Exception\TException;
 
 /**
diff --git a/lib/php/lib/Thrift/Protocol/TSimpleJSONProtocol.php b/lib/php/lib/Protocol/TSimpleJSONProtocol.php
similarity index 98%
rename from lib/php/lib/Thrift/Protocol/TSimpleJSONProtocol.php
rename to lib/php/lib/Protocol/TSimpleJSONProtocol.php
index 9cf90bd..1cf1f64 100644
--- a/lib/php/lib/Thrift/Protocol/TSimpleJSONProtocol.php
+++ b/lib/php/lib/Protocol/TSimpleJSONProtocol.php
@@ -54,7 +54,8 @@
     /**
      * Push a new write context onto the stack.
      */
-    protected function pushWriteContext(Context $c) {
+    protected function pushWriteContext(Context $c)
+    {
         $this->writeContextStack_[] = $this->writeContext_;
         $this->writeContext_ = $c;
     }
@@ -62,14 +63,16 @@
     /**
      * Pop the last write context off the stack
      */
-    protected function popWriteContext() {
+    protected function popWriteContext()
+    {
         $this->writeContext_ = array_pop($this->writeContextStack_);
     }
 
     /**
      * Used to make sure that we are not encountering a map whose keys are containers
      */
-    protected function assertContextIsNotMapKey($invalidKeyType) {
+    protected function assertContextIsNotMapKey($invalidKeyType)
+    {
         if ($this->writeContext_->isMapKey()) {
             throw new CollectionMapKeyException(
                 "Cannot serialize a map with keys that are of type " .
diff --git a/lib/php/lib/Serializer/TBinarySerializer.php b/lib/php/lib/Serializer/TBinarySerializer.php
new file mode 100644
index 0000000..9d2b147
--- /dev/null
+++ b/lib/php/lib/Serializer/TBinarySerializer.php
@@ -0,0 +1,87 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.protocol
+ * @author: rmarin (marin.radu@facebook.com)
+ */
+
+namespace Thrift\Serializer;
+
+use Thrift\Transport\TMemoryBuffer;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Type\TMessageType;
+
+/**
+ * Utility class for serializing and deserializing
+ * a thrift object using TBinaryProtocolAccelerated.
+ */
+class TBinarySerializer
+{
+    // NOTE(rmarin): Because thrift_protocol_write_binary
+    // adds a begin message prefix, you cannot specify
+    // a transport in which to serialize an object. It has to
+    // be a string. Otherwise we will break the compatibility with
+    // normal deserialization.
+    public static function serialize($object)
+    {
+        $transport = new TMemoryBuffer();
+        $protocol = new TBinaryProtocolAccelerated($transport);
+        if (function_exists('thrift_protocol_write_binary')) {
+            thrift_protocol_write_binary(
+                $protocol,
+                $object->getName(),
+                TMessageType::REPLY,
+                $object,
+                0,
+                $protocol->isStrictWrite()
+            );
+
+            $protocol->readMessageBegin($unused_name, $unused_type, $unused_seqid);
+        } else {
+            $object->write($protocol);
+        }
+        $protocol->getTransport()->flush();
+
+        return $transport->getBuffer();
+    }
+
+    public static function deserialize($string_object, $class_name, $buffer_size = 8192)
+    {
+        $transport = new TMemoryBuffer();
+        $protocol = new TBinaryProtocolAccelerated($transport);
+        if (function_exists('thrift_protocol_read_binary')) {
+            // NOTE (t.heintz) TBinaryProtocolAccelerated internally wraps our TMemoryBuffer in a
+            // TBufferedTransport, so we have to retrieve it again or risk losing data when writing
+            // less than 512 bytes to the transport (see the comment there as well).
+            // @see THRIFT-1579
+            $protocol->writeMessageBegin('', TMessageType::REPLY, 0);
+            $protocolTransport = $protocol->getTransport();
+            $protocolTransport->write($string_object);
+            $protocolTransport->flush();
+
+            return thrift_protocol_read_binary($protocol, $class_name, $protocol->isStrictRead(), $buffer_size);
+        } else {
+            $transport->write($string_object);
+            $object = new $class_name();
+            $object->read($protocol);
+
+            return $object;
+        }
+    }
+}
diff --git a/lib/php/lib/Server/TForkingServer.php b/lib/php/lib/Server/TForkingServer.php
new file mode 100644
index 0000000..0bb6e91
--- /dev/null
+++ b/lib/php/lib/Server/TForkingServer.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TTransport;
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+
+/**
+ * A forking implementation of a Thrift server.
+ *
+ * @package thrift.server
+ */
+class TForkingServer extends TServer
+{
+    /**
+     * Flag for the main serving loop
+     *
+     * @var bool
+     */
+    private $stop_ = false;
+
+    /**
+     * List of children.
+     *
+     * @var array
+     */
+    protected $children_ = array();
+
+    /**
+     * Listens for new client using the supplied
+     * transport. We fork when a new connection
+     * arrives.
+     *
+     * @return void
+     */
+    public function serve()
+    {
+        $this->transport_->listen();
+
+        while (!$this->stop_) {
+            try {
+                $transport = $this->transport_->accept();
+
+                if ($transport != null) {
+                    $pid = pcntl_fork();
+
+                    if ($pid > 0) {
+                        $this->handleParent($transport, $pid);
+                    } elseif ($pid === 0) {
+                        $this->handleChild($transport);
+                    } else {
+                        throw new TException('Failed to fork');
+                    }
+                }
+            } catch (TTransportException $e) {
+            }
+
+            $this->collectChildren();
+        }
+    }
+
+    /**
+     * Code run by the parent
+     *
+     * @param TTransport $transport
+     * @param int $pid
+     * @return void
+     */
+    private function handleParent(TTransport $transport, $pid)
+    {
+        $this->children_[$pid] = $transport;
+    }
+
+    /**
+     * Code run by the child.
+     *
+     * @param TTransport $transport
+     * @return void
+     */
+    private function handleChild(TTransport $transport)
+    {
+        try {
+            $inputTransport = $this->inputTransportFactory_->getTransport($transport);
+            $outputTransport = $this->outputTransportFactory_->getTransport($transport);
+            $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
+            $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
+            while ($this->processor_->process($inputProtocol, $outputProtocol)) {
+            }
+            @$transport->close();
+        } catch (TTransportException $e) {
+        }
+
+        exit(0);
+    }
+
+    /**
+     * Collects any children we may have
+     *
+     * @return void
+     */
+    private function collectChildren()
+    {
+        foreach ($this->children_ as $pid => $transport) {
+            if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
+                unset($this->children_[$pid]);
+                if ($transport) {
+                    @$transport->close();
+                }
+            }
+        }
+    }
+
+    /**
+     * Stops the server running. Kills the transport
+     * and then stops the main serving loop
+     *
+     * @return void
+     */
+    public function stop()
+    {
+        $this->transport_->close();
+        $this->stop_ = true;
+    }
+}
diff --git a/lib/php/lib/Server/TSSLServerSocket.php b/lib/php/lib/Server/TSSLServerSocket.php
new file mode 100644
index 0000000..ac589b7
--- /dev/null
+++ b/lib/php/lib/Server/TSSLServerSocket.php
@@ -0,0 +1,97 @@
+<?php
+/*
+ * 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.
+ *
+ */
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TSSLSocket;
+
+/**
+ * Socket implementation of a server agent.
+ *
+ * @package thrift.transport
+ */
+class TSSLServerSocket extends TServerSocket
+{
+    /**
+     * Remote port
+     *
+     * @var resource
+     */
+    protected $context_ = null;
+
+    /**
+     * ServerSocket constructor
+     *
+     * @param string $host Host to listen on
+     * @param int $port Port to listen on
+     * @param resource $context Stream context
+     * @return void
+     */
+    public function __construct($host = 'localhost', $port = 9090, $context = null)
+    {
+        $ssl_host = $this->getSSLHost($host);
+        parent::__construct($ssl_host, $port);
+        $this->context_ = $context;
+    }
+
+    public function getSSLHost($host)
+    {
+        $transport_protocol_loc = strpos($host, "://");
+        if ($transport_protocol_loc === false) {
+            $host = 'ssl://' . $host;
+        }
+        return $host;
+    }
+
+    /**
+     * Opens a new socket server handle
+     *
+     * @return void
+     */
+    public function listen()
+    {
+        $this->listener_ = @stream_socket_server(
+            $this->host_ . ':' . $this->port_,
+            $errno,
+            $errstr,
+            STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
+            $this->context_
+        );
+    }
+
+    /**
+     * Implementation of accept. If not client is accepted in the given time
+     *
+     * @return TSocket
+     */
+    protected function acceptImpl()
+    {
+        $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
+        if (!$handle) {
+            return null;
+        }
+
+        $socket = new TSSLSocket();
+        $socket->setHandle($handle);
+
+        return $socket;
+    }
+}
diff --git a/lib/php/lib/Server/TServer.php b/lib/php/lib/Server/TServer.php
new file mode 100644
index 0000000..268c378
--- /dev/null
+++ b/lib/php/lib/Server/TServer.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Factory\TTransportFactory;
+use Thrift\Factory\TProtocolFactory;
+
+/**
+ * Generic class for a Thrift server.
+ *
+ * @package thrift.server
+ */
+abstract class TServer
+{
+    /**
+     * Processor to handle new clients
+     *
+     * @var TProcessor
+     */
+    protected $processor_;
+
+    /**
+     * Server transport to be used for listening
+     * and accepting new clients
+     *
+     * @var TServerTransport
+     */
+    protected $transport_;
+
+    /**
+     * Input transport factory
+     *
+     * @var TTransportFactory
+     */
+    protected $inputTransportFactory_;
+
+    /**
+     * Output transport factory
+     *
+     * @var TTransportFactory
+     */
+    protected $outputTransportFactory_;
+
+    /**
+     * Input protocol factory
+     *
+     * @var TProtocolFactory
+     */
+    protected $inputProtocolFactory_;
+
+    /**
+     * Output protocol factory
+     *
+     * @var TProtocolFactory
+     */
+    protected $outputProtocolFactory_;
+
+    /**
+     * Sets up all the factories, etc
+     *
+     * @param object $processor
+     * @param TServerTransport $transport
+     * @param TTransportFactory $inputTransportFactory
+     * @param TTransportFactory $outputTransportFactory
+     * @param TProtocolFactory $inputProtocolFactory
+     * @param TProtocolFactory $outputProtocolFactory
+     * @return void
+     */
+    public function __construct(
+        $processor,
+        TServerTransport $transport,
+        TTransportFactory $inputTransportFactory,
+        TTransportFactory $outputTransportFactory,
+        TProtocolFactory $inputProtocolFactory,
+        TProtocolFactory $outputProtocolFactory
+    ) {
+        $this->processor_ = $processor;
+        $this->transport_ = $transport;
+        $this->inputTransportFactory_ = $inputTransportFactory;
+        $this->outputTransportFactory_ = $outputTransportFactory;
+        $this->inputProtocolFactory_ = $inputProtocolFactory;
+        $this->outputProtocolFactory_ = $outputProtocolFactory;
+    }
+
+    /**
+     * Serves the server. This should never return
+     * unless a problem permits it to do so or it
+     * is interrupted intentionally
+     *
+     * @abstract
+     * @return void
+     */
+    abstract public function serve();
+
+    /**
+     * Stops the server serving
+     *
+     * @abstract
+     * @return void
+     */
+    abstract public function stop();
+}
diff --git a/lib/php/lib/Server/TServerSocket.php b/lib/php/lib/Server/TServerSocket.php
new file mode 100644
index 0000000..8f38fb2
--- /dev/null
+++ b/lib/php/lib/Server/TServerSocket.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TSocket;
+
+/**
+ * Socket implementation of a server agent.
+ *
+ * @package thrift.transport
+ */
+class TServerSocket extends TServerTransport
+{
+    /**
+     * Handle for the listener socket
+     *
+     * @var resource
+     */
+    protected $listener_;
+
+    /**
+     * Port for the listener to listen on
+     *
+     * @var int
+     */
+    protected $port_;
+
+    /**
+     * Timeout when listening for a new client
+     *
+     * @var int
+     */
+    protected $acceptTimeout_ = 30000;
+
+    /**
+     * Host to listen on
+     *
+     * @var string
+     */
+    protected $host_;
+
+    /**
+     * ServerSocket constructor
+     *
+     * @param string $host Host to listen on
+     * @param int $port Port to listen on
+     * @return void
+     */
+    public function __construct($host = 'localhost', $port = 9090)
+    {
+        $this->host_ = $host;
+        $this->port_ = $port;
+    }
+
+    /**
+     * Sets the accept timeout
+     *
+     * @param int $acceptTimeout
+     * @return void
+     */
+    public function setAcceptTimeout($acceptTimeout)
+    {
+        $this->acceptTimeout_ = $acceptTimeout;
+    }
+
+    /**
+     * Opens a new socket server handle
+     *
+     * @return void
+     */
+    public function listen()
+    {
+        $this->listener_ = stream_socket_server('tcp://' . $this->host_ . ':' . $this->port_);
+    }
+
+    /**
+     * Closes the socket server handle
+     *
+     * @return void
+     */
+    public function close()
+    {
+        @fclose($this->listener_);
+        $this->listener_ = null;
+    }
+
+    /**
+     * Implementation of accept. If not client is accepted in the given time
+     *
+     * @return TSocket
+     */
+    protected function acceptImpl()
+    {
+        $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
+        if (!$handle) {
+            return null;
+        }
+
+        $socket = new TSocket();
+        $socket->setHandle($handle);
+
+        return $socket;
+    }
+}
diff --git a/lib/php/lib/Server/TServerTransport.php b/lib/php/lib/Server/TServerTransport.php
new file mode 100644
index 0000000..15a27af
--- /dev/null
+++ b/lib/php/lib/Server/TServerTransport.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Exception\TTransportException;
+
+/**
+ * Generic class for Server agent.
+ *
+ * @package thrift.transport
+ */
+abstract class TServerTransport
+{
+    /**
+     * List for new clients
+     *
+     * @abstract
+     * @return void
+     */
+    abstract public function listen();
+
+    /**
+     * Close the server
+     *
+     * @abstract
+     * @return void
+     */
+    abstract public function close();
+
+    /**
+     * Subclasses should use this to implement
+     * accept.
+     *
+     * @abstract
+     * @return TTransport
+     */
+    abstract protected function acceptImpl();
+
+    /**
+     * Uses the accept implemtation. If null is returned, an
+     * exception is thrown.
+     *
+     * @throws TTransportException
+     * @return TTransport
+     */
+    public function accept()
+    {
+        $transport = $this->acceptImpl();
+
+        if ($transport == null) {
+            throw new TTransportException("accept() may not return NULL");
+        }
+
+        return $transport;
+    }
+}
diff --git a/lib/php/lib/Server/TSimpleServer.php b/lib/php/lib/Server/TSimpleServer.php
new file mode 100644
index 0000000..4c1dda5
--- /dev/null
+++ b/lib/php/lib/Server/TSimpleServer.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Exception\TTransportException;
+
+/**
+ * Simple implemtation of a Thrift server.
+ *
+ * @package thrift.server
+ */
+class TSimpleServer extends TServer
+{
+    /**
+     * Flag for the main serving loop
+     *
+     * @var bool
+     */
+    private $stop_ = false;
+
+    /**
+     * Listens for new client using the supplied
+     * transport. It handles TTransportExceptions
+     * to avoid timeouts etc killing it
+     *
+     * @return void
+     */
+    public function serve()
+    {
+        $this->transport_->listen();
+
+        while (!$this->stop_) {
+            try {
+                $transport = $this->transport_->accept();
+
+                if ($transport != null) {
+                    $inputTransport = $this->inputTransportFactory_->getTransport($transport);
+                    $outputTransport = $this->outputTransportFactory_->getTransport($transport);
+                    $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
+                    $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
+                    while ($this->processor_->process($inputProtocol, $outputProtocol)) {
+                    }
+                }
+            } catch (TTransportException $e) {
+            }
+        }
+    }
+
+    /**
+     * Stops the server running. Kills the transport
+     * and then stops the main serving loop
+     *
+     * @return void
+     */
+    public function stop()
+    {
+        $this->transport_->close();
+        $this->stop_ = true;
+    }
+}
diff --git a/lib/php/lib/StoredMessageProtocol.php b/lib/php/lib/StoredMessageProtocol.php
new file mode 100644
index 0000000..c4aaaa9
--- /dev/null
+++ b/lib/php/lib/StoredMessageProtocol.php
@@ -0,0 +1,53 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.processor
+ */
+
+namespace Thrift;
+
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TProtocolDecorator;
+
+/**
+ *  Our goal was to work with any protocol. In order to do that, we needed
+ *  to allow them to call readMessageBegin() and get the Message in exactly
+ *  the standard format, without the service name prepended to the Message name.
+ */
+class StoredMessageProtocol extends TProtocolDecorator
+{
+    private $fname_;
+    private $mtype_;
+    private $rseqid_;
+
+    public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid)
+    {
+        parent::__construct($protocol);
+        $this->fname_  = $fname;
+        $this->mtype_  = $mtype;
+        $this->rseqid_ = $rseqid;
+    }
+
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        $name  = $this->fname_;
+        $type  = $this->mtype_;
+        $seqid = $this->rseqid_;
+    }
+}
diff --git a/lib/php/lib/Thrift/StringFunc/Core.php b/lib/php/lib/StringFunc/Core.php
similarity index 100%
rename from lib/php/lib/Thrift/StringFunc/Core.php
rename to lib/php/lib/StringFunc/Core.php
diff --git a/lib/php/lib/Thrift/StringFunc/Mbstring.php b/lib/php/lib/StringFunc/Mbstring.php
similarity index 100%
rename from lib/php/lib/Thrift/StringFunc/Mbstring.php
rename to lib/php/lib/StringFunc/Mbstring.php
diff --git a/lib/php/lib/Thrift/StringFunc/TStringFunc.php b/lib/php/lib/StringFunc/TStringFunc.php
similarity index 100%
rename from lib/php/lib/Thrift/StringFunc/TStringFunc.php
rename to lib/php/lib/StringFunc/TStringFunc.php
diff --git a/lib/php/lib/Thrift/TMultiplexedProcessor.php b/lib/php/lib/TMultiplexedProcessor.php
similarity index 84%
rename from lib/php/lib/Thrift/TMultiplexedProcessor.php
rename to lib/php/lib/TMultiplexedProcessor.php
index 138f95b..a64a968 100644
--- a/lib/php/lib/Thrift/TMultiplexedProcessor.php
+++ b/lib/php/lib/TMultiplexedProcessor.php
@@ -25,7 +25,6 @@
 use Thrift\Exception\TException;
 use Thrift\Protocol\TProtocol;
 use Thrift\Protocol\TMultiplexedProtocol;
-use Thrift\Protocol\TProtocolDecorator;
 use Thrift\Type\TMessageType;
 
 /**
@@ -112,32 +111,8 @@
         $processor = $this->serviceProcessorMap_[$serviceName];
 
         return $processor->process(
-            new StoredMessageProtocol($input, $messageName, $mtype, $rseqid), $output
+            new StoredMessageProtocol($input, $messageName, $mtype, $rseqid),
+            $output
         );
     }
 }
-
-/**
- *  Our goal was to work with any protocol. In order to do that, we needed
- *  to allow them to call readMessageBegin() and get the Message in exactly
- *  the standard format, without the service name prepended to the Message name.
- */
-class StoredMessageProtocol extends TProtocolDecorator
-{
-    private $fname_, $mtype_, $rseqid_;
-
-    public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid)
-    {
-        parent::__construct($protocol);
-        $this->fname_  = $fname;
-        $this->mtype_  = $mtype;
-        $this->rseqid_ = $rseqid;
-    }
-
-    public function readMessageBegin(&$name, &$type, &$seqid)
-    {
-        $name  = $this->fname_;
-        $type  = $this->mtype_;
-        $seqid = $this->rseqid_;
-    }
-}
diff --git a/lib/php/lib/Thrift/Base/TBase.php b/lib/php/lib/Thrift/Base/TBase.php
deleted file mode 100644
index 4195f75..0000000
--- a/lib/php/lib/Thrift/Base/TBase.php
+++ /dev/null
@@ -1,380 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift
- */
-
-namespace Thrift\Base;
-
-use Thrift\Type\TType;
-
-/**
- * Base class from which other Thrift structs extend. This is so that we can
- * cut back on the size of the generated code which is turning out to have a
- * nontrivial cost just to load thanks to the wondrously abysmal implementation
- * of PHP. Note that code is intentionally duplicated in here to avoid making
- * function calls for every field or member of a container..
- */
-abstract class TBase
-{
-  static $tmethod = array(TType::BOOL   => 'Bool',
-                          TType::BYTE   => 'Byte',
-                          TType::I16    => 'I16',
-                          TType::I32    => 'I32',
-                          TType::I64    => 'I64',
-                          TType::DOUBLE => 'Double',
-                          TType::STRING => 'String');
-
-  abstract public function read($input);
-
-  abstract public function write($output);
-
-  public function __construct($spec=null, $vals=null)
-  {
-    if (is_array($spec) && is_array($vals)) {
-      foreach ($spec as $fid => $fspec) {
-        $var = $fspec['var'];
-        if (isset($vals[$var])) {
-          $this->$var = $vals[$var];
-        }
-      }
-    }
-  }
-
-  public function __wakeup()
-  {
-    $this->__construct(get_object_vars($this));
-  }
-
-  private function _readMap(&$var, $spec, $input)
-  {
-    $xfer = 0;
-    $ktype = $spec['ktype'];
-    $vtype = $spec['vtype'];
-    $kread = $vread = null;
-    if (isset(TBase::$tmethod[$ktype])) {
-      $kread = 'read'.TBase::$tmethod[$ktype];
-    } else {
-      $kspec = $spec['key'];
-    }
-    if (isset(TBase::$tmethod[$vtype])) {
-      $vread = 'read'.TBase::$tmethod[$vtype];
-    } else {
-      $vspec = $spec['val'];
-    }
-    $var = array();
-    $_ktype = $_vtype = $size = 0;
-    $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
-    for ($i = 0; $i < $size; ++$i) {
-      $key = $val = null;
-      if ($kread !== null) {
-        $xfer += $input->$kread($key);
-      } else {
-        switch ($ktype) {
-        case TType::STRUCT:
-          $class = $kspec['class'];
-          $key = new $class();
-          $xfer += $key->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($key, $kspec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($key, $kspec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($key, $kspec, $input, true);
-          break;
-        }
-      }
-      if ($vread !== null) {
-        $xfer += $input->$vread($val);
-      } else {
-        switch ($vtype) {
-        case TType::STRUCT:
-          $class = $vspec['class'];
-          $val = new $class();
-          $xfer += $val->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($val, $vspec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($val, $vspec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($val, $vspec, $input, true);
-          break;
-        }
-      }
-      $var[$key] = $val;
-    }
-    $xfer += $input->readMapEnd();
-
-    return $xfer;
-  }
-
-  private function _readList(&$var, $spec, $input, $set=false)
-  {
-    $xfer = 0;
-    $etype = $spec['etype'];
-    $eread = $vread = null;
-    if (isset(TBase::$tmethod[$etype])) {
-      $eread = 'read'.TBase::$tmethod[$etype];
-    } else {
-      $espec = $spec['elem'];
-    }
-    $var = array();
-    $_etype = $size = 0;
-    if ($set) {
-      $xfer += $input->readSetBegin($_etype, $size);
-    } else {
-      $xfer += $input->readListBegin($_etype, $size);
-    }
-    for ($i = 0; $i < $size; ++$i) {
-      $elem = null;
-      if ($eread !== null) {
-        $xfer += $input->$eread($elem);
-      } else {
-        $espec = $spec['elem'];
-        switch ($etype) {
-        case TType::STRUCT:
-          $class = $espec['class'];
-          $elem = new $class();
-          $xfer += $elem->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($elem, $espec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($elem, $espec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($elem, $espec, $input, true);
-          break;
-        }
-      }
-      if ($set) {
-        $var[$elem] = true;
-      } else {
-        $var []= $elem;
-      }
-    }
-    if ($set) {
-      $xfer += $input->readSetEnd();
-    } else {
-      $xfer += $input->readListEnd();
-    }
-
-    return $xfer;
-  }
-
-  protected function _read($class, $spec, $input)
-  {
-    $xfer = 0;
-    $fname = null;
-    $ftype = 0;
-    $fid = 0;
-    $xfer += $input->readStructBegin($fname);
-    while (true) {
-      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
-      if ($ftype == TType::STOP) {
-        break;
-      }
-      if (isset($spec[$fid])) {
-        $fspec = $spec[$fid];
-        $var = $fspec['var'];
-        if ($ftype == $fspec['type']) {
-          $xfer = 0;
-          if (isset(TBase::$tmethod[$ftype])) {
-            $func = 'read'.TBase::$tmethod[$ftype];
-            $xfer += $input->$func($this->$var);
-          } else {
-            switch ($ftype) {
-            case TType::STRUCT:
-              $class = $fspec['class'];
-              $this->$var = new $class();
-              $xfer += $this->$var->read($input);
-              break;
-            case TType::MAP:
-              $xfer += $this->_readMap($this->$var, $fspec, $input);
-              break;
-            case TType::LST:
-              $xfer += $this->_readList($this->$var, $fspec, $input, false);
-              break;
-            case TType::SET:
-              $xfer += $this->_readList($this->$var, $fspec, $input, true);
-              break;
-            }
-          }
-        } else {
-          $xfer += $input->skip($ftype);
-        }
-      } else {
-        $xfer += $input->skip($ftype);
-      }
-      $xfer += $input->readFieldEnd();
-    }
-    $xfer += $input->readStructEnd();
-
-    return $xfer;
-  }
-
-  private function _writeMap($var, $spec, $output)
-  {
-    $xfer = 0;
-    $ktype = $spec['ktype'];
-    $vtype = $spec['vtype'];
-    $kwrite = $vwrite = null;
-    if (isset(TBase::$tmethod[$ktype])) {
-      $kwrite = 'write'.TBase::$tmethod[$ktype];
-    } else {
-      $kspec = $spec['key'];
-    }
-    if (isset(TBase::$tmethod[$vtype])) {
-      $vwrite = 'write'.TBase::$tmethod[$vtype];
-    } else {
-      $vspec = $spec['val'];
-    }
-    $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
-    foreach ($var as $key => $val) {
-      if (isset($kwrite)) {
-        $xfer += $output->$kwrite($key);
-      } else {
-        switch ($ktype) {
-        case TType::STRUCT:
-          $xfer += $key->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($key, $kspec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($key, $kspec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($key, $kspec, $output, true);
-          break;
-        }
-      }
-      if (isset($vwrite)) {
-        $xfer += $output->$vwrite($val);
-      } else {
-        switch ($vtype) {
-        case TType::STRUCT:
-          $xfer += $val->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($val, $vspec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($val, $vspec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($val, $vspec, $output, true);
-          break;
-        }
-      }
-    }
-    $xfer += $output->writeMapEnd();
-
-    return $xfer;
-  }
-
-  private function _writeList($var, $spec, $output, $set=false)
-  {
-    $xfer = 0;
-    $etype = $spec['etype'];
-    $ewrite = null;
-    if (isset(TBase::$tmethod[$etype])) {
-      $ewrite = 'write'.TBase::$tmethod[$etype];
-    } else {
-      $espec = $spec['elem'];
-    }
-    if ($set) {
-      $xfer += $output->writeSetBegin($etype, count($var));
-    } else {
-      $xfer += $output->writeListBegin($etype, count($var));
-    }
-    foreach ($var as $key => $val) {
-      $elem = $set ? $key : $val;
-      if (isset($ewrite)) {
-        $xfer += $output->$ewrite($elem);
-      } else {
-        switch ($etype) {
-        case TType::STRUCT:
-          $xfer += $elem->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($elem, $espec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($elem, $espec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($elem, $espec, $output, true);
-          break;
-        }
-      }
-    }
-    if ($set) {
-      $xfer += $output->writeSetEnd();
-    } else {
-      $xfer += $output->writeListEnd();
-    }
-
-    return $xfer;
-  }
-
-  protected function _write($class, $spec, $output)
-  {
-    $xfer = 0;
-    $xfer += $output->writeStructBegin($class);
-    foreach ($spec as $fid => $fspec) {
-      $var = $fspec['var'];
-      if ($this->$var !== null) {
-        $ftype = $fspec['type'];
-        $xfer += $output->writeFieldBegin($var, $ftype, $fid);
-        if (isset(TBase::$tmethod[$ftype])) {
-          $func = 'write'.TBase::$tmethod[$ftype];
-          $xfer += $output->$func($this->$var);
-        } else {
-          switch ($ftype) {
-          case TType::STRUCT:
-            $xfer += $this->$var->write($output);
-            break;
-          case TType::MAP:
-            $xfer += $this->_writeMap($this->$var, $fspec, $output);
-            break;
-          case TType::LST:
-            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
-            break;
-          case TType::SET:
-            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
-            break;
-          }
-        }
-        $xfer += $output->writeFieldEnd();
-      }
-    }
-    $xfer += $output->writeFieldStop();
-    $xfer += $output->writeStructEnd();
-
-    return $xfer;
-  }
-}
diff --git a/lib/php/lib/Thrift/Exception/TApplicationException.php b/lib/php/lib/Thrift/Exception/TApplicationException.php
deleted file mode 100644
index b1689fc..0000000
--- a/lib/php/lib/Thrift/Exception/TApplicationException.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift
- */
-
-namespace Thrift\Exception;
-
-use Thrift\Type\TType;
-
-class TApplicationException extends TException
-{
-  static $_TSPEC =
-    array(1 => array('var' => 'message',
-                     'type' => TType::STRING),
-          2 => array('var' => 'code',
-                     'type' => TType::I32));
-
-  const UNKNOWN = 0;
-  const UNKNOWN_METHOD = 1;
-  const INVALID_MESSAGE_TYPE = 2;
-  const WRONG_METHOD_NAME = 3;
-  const BAD_SEQUENCE_ID = 4;
-  const MISSING_RESULT = 5;
-  const INTERNAL_ERROR = 6;
-  const PROTOCOL_ERROR = 7;
-  const INVALID_TRANSFORM = 8;
-  const INVALID_PROTOCOL = 9;
-  const UNSUPPORTED_CLIENT_TYPE = 10;
-
-  public function __construct($message=null, $code=0)
-  {
-    parent::__construct($message, $code);
-  }
-
-  public function read($output)
-  {
-    return $this->_read('TApplicationException', self::$_TSPEC, $output);
-  }
-
-  public function write($output)
-  {
-    $xfer = 0;
-    $xfer += $output->writeStructBegin('TApplicationException');
-    if ($message = $this->getMessage()) {
-      $xfer += $output->writeFieldBegin('message', TType::STRING, 1);
-      $xfer += $output->writeString($message);
-      $xfer += $output->writeFieldEnd();
-    }
-    if ($code = $this->getCode()) {
-      $xfer += $output->writeFieldBegin('type', TType::I32, 2);
-      $xfer += $output->writeI32($code);
-      $xfer += $output->writeFieldEnd();
-    }
-    $xfer += $output->writeFieldStop();
-    $xfer += $output->writeStructEnd();
-
-    return $xfer;
-  }
-}
diff --git a/lib/php/lib/Thrift/Exception/TException.php b/lib/php/lib/Thrift/Exception/TException.php
deleted file mode 100644
index 5c06843..0000000
--- a/lib/php/lib/Thrift/Exception/TException.php
+++ /dev/null
@@ -1,383 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift
- */
-
-namespace Thrift\Exception;
-
-use Thrift\Type\TType;
-use Thrift\Base\TBase;
-
-/**
- * NOTE(mcslee): This currently contains a ton of duplicated code from TBase
- * because we need to save CPU cycles and this is not yet in an extension.
- * Ideally we'd multiply-inherit TException from both Exception and Base, but
- * that's not possible in PHP and there are no modules either, so for now we
- * apologetically take a trip to HackTown.
- *
- * Can be called with standard Exception constructor (message, code) or with
- * Thrift Base object constructor (spec, vals).
- *
- * @param mixed $p1 Message (string) or type-spec (array)
- * @param mixed $p2 Code (integer) or values (array)
- */
-class TException extends \Exception
-{
-  public function __construct($p1=null, $p2=0)
-  {
-    if (is_array($p1) && is_array($p2)) {
-      $spec = $p1;
-      $vals = $p2;
-      foreach ($spec as $fid => $fspec) {
-        $var = $fspec['var'];
-        if (isset($vals[$var])) {
-          $this->$var = $vals[$var];
-        }
-      }
-    } else {
-      parent::__construct($p1, $p2);
-    }
-  }
-
-  static $tmethod = array(TType::BOOL   => 'Bool',
-                          TType::BYTE   => 'Byte',
-                          TType::I16    => 'I16',
-                          TType::I32    => 'I32',
-                          TType::I64    => 'I64',
-                          TType::DOUBLE => 'Double',
-                          TType::STRING => 'String');
-
-  private function _readMap(&$var, $spec, $input)
-  {
-    $xfer = 0;
-    $ktype = $spec['ktype'];
-    $vtype = $spec['vtype'];
-    $kread = $vread = null;
-    if (isset(TBase::$tmethod[$ktype])) {
-      $kread = 'read'.TBase::$tmethod[$ktype];
-    } else {
-      $kspec = $spec['key'];
-    }
-    if (isset(TBase::$tmethod[$vtype])) {
-      $vread = 'read'.TBase::$tmethod[$vtype];
-    } else {
-      $vspec = $spec['val'];
-    }
-    $var = array();
-    $_ktype = $_vtype = $size = 0;
-    $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
-    for ($i = 0; $i < $size; ++$i) {
-      $key = $val = null;
-      if ($kread !== null) {
-        $xfer += $input->$kread($key);
-      } else {
-        switch ($ktype) {
-        case TType::STRUCT:
-          $class = $kspec['class'];
-          $key = new $class();
-          $xfer += $key->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($key, $kspec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($key, $kspec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($key, $kspec, $input, true);
-          break;
-        }
-      }
-      if ($vread !== null) {
-        $xfer += $input->$vread($val);
-      } else {
-        switch ($vtype) {
-        case TType::STRUCT:
-          $class = $vspec['class'];
-          $val = new $class();
-          $xfer += $val->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($val, $vspec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($val, $vspec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($val, $vspec, $input, true);
-          break;
-        }
-      }
-      $var[$key] = $val;
-    }
-    $xfer += $input->readMapEnd();
-
-    return $xfer;
-  }
-
-  private function _readList(&$var, $spec, $input, $set=false)
-  {
-    $xfer = 0;
-    $etype = $spec['etype'];
-    $eread = $vread = null;
-    if (isset(TBase::$tmethod[$etype])) {
-      $eread = 'read'.TBase::$tmethod[$etype];
-    } else {
-      $espec = $spec['elem'];
-    }
-    $var = array();
-    $_etype = $size = 0;
-    if ($set) {
-      $xfer += $input->readSetBegin($_etype, $size);
-    } else {
-      $xfer += $input->readListBegin($_etype, $size);
-    }
-    for ($i = 0; $i < $size; ++$i) {
-      $elem = null;
-      if ($eread !== null) {
-        $xfer += $input->$eread($elem);
-      } else {
-        $espec = $spec['elem'];
-        switch ($etype) {
-        case TType::STRUCT:
-          $class = $espec['class'];
-          $elem = new $class();
-          $xfer += $elem->read($input);
-          break;
-        case TType::MAP:
-          $xfer += $this->_readMap($elem, $espec, $input);
-          break;
-        case TType::LST:
-          $xfer += $this->_readList($elem, $espec, $input, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_readList($elem, $espec, $input, true);
-          break;
-        }
-      }
-      if ($set) {
-        $var[$elem] = true;
-      } else {
-        $var []= $elem;
-      }
-    }
-    if ($set) {
-      $xfer += $input->readSetEnd();
-    } else {
-      $xfer += $input->readListEnd();
-    }
-
-    return $xfer;
-  }
-
-  protected function _read($class, $spec, $input)
-  {
-    $xfer = 0;
-    $fname = null;
-    $ftype = 0;
-    $fid = 0;
-    $xfer += $input->readStructBegin($fname);
-    while (true) {
-      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
-      if ($ftype == TType::STOP) {
-        break;
-      }
-      if (isset($spec[$fid])) {
-        $fspec = $spec[$fid];
-        $var = $fspec['var'];
-        if ($ftype == $fspec['type']) {
-          $xfer = 0;
-          if (isset(TBase::$tmethod[$ftype])) {
-            $func = 'read'.TBase::$tmethod[$ftype];
-            $xfer += $input->$func($this->$var);
-          } else {
-            switch ($ftype) {
-            case TType::STRUCT:
-              $class = $fspec['class'];
-              $this->$var = new $class();
-              $xfer += $this->$var->read($input);
-              break;
-            case TType::MAP:
-              $xfer += $this->_readMap($this->$var, $fspec, $input);
-              break;
-            case TType::LST:
-              $xfer += $this->_readList($this->$var, $fspec, $input, false);
-              break;
-            case TType::SET:
-              $xfer += $this->_readList($this->$var, $fspec, $input, true);
-              break;
-            }
-          }
-        } else {
-          $xfer += $input->skip($ftype);
-        }
-      } else {
-        $xfer += $input->skip($ftype);
-      }
-      $xfer += $input->readFieldEnd();
-    }
-    $xfer += $input->readStructEnd();
-
-    return $xfer;
-  }
-
-  private function _writeMap($var, $spec, $output)
-  {
-    $xfer = 0;
-    $ktype = $spec['ktype'];
-    $vtype = $spec['vtype'];
-    $kwrite = $vwrite = null;
-    if (isset(TBase::$tmethod[$ktype])) {
-      $kwrite = 'write'.TBase::$tmethod[$ktype];
-    } else {
-      $kspec = $spec['key'];
-    }
-    if (isset(TBase::$tmethod[$vtype])) {
-      $vwrite = 'write'.TBase::$tmethod[$vtype];
-    } else {
-      $vspec = $spec['val'];
-    }
-    $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
-    foreach ($var as $key => $val) {
-      if (isset($kwrite)) {
-        $xfer += $output->$kwrite($key);
-      } else {
-        switch ($ktype) {
-        case TType::STRUCT:
-          $xfer += $key->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($key, $kspec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($key, $kspec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($key, $kspec, $output, true);
-          break;
-        }
-      }
-      if (isset($vwrite)) {
-        $xfer += $output->$vwrite($val);
-      } else {
-        switch ($vtype) {
-        case TType::STRUCT:
-          $xfer += $val->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($val, $vspec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($val, $vspec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($val, $vspec, $output, true);
-          break;
-        }
-      }
-    }
-    $xfer += $output->writeMapEnd();
-
-    return $xfer;
-  }
-
-  private function _writeList($var, $spec, $output, $set=false)
-  {
-    $xfer = 0;
-    $etype = $spec['etype'];
-    $ewrite = null;
-    if (isset(TBase::$tmethod[$etype])) {
-      $ewrite = 'write'.TBase::$tmethod[$etype];
-    } else {
-      $espec = $spec['elem'];
-    }
-    if ($set) {
-      $xfer += $output->writeSetBegin($etype, count($var));
-    } else {
-      $xfer += $output->writeListBegin($etype, count($var));
-    }
-    foreach ($var as $key => $val) {
-      $elem = $set ? $key : $val;
-      if (isset($ewrite)) {
-        $xfer += $output->$ewrite($elem);
-      } else {
-        switch ($etype) {
-        case TType::STRUCT:
-          $xfer += $elem->write($output);
-          break;
-        case TType::MAP:
-          $xfer += $this->_writeMap($elem, $espec, $output);
-          break;
-        case TType::LST:
-          $xfer += $this->_writeList($elem, $espec, $output, false);
-          break;
-        case TType::SET:
-          $xfer += $this->_writeList($elem, $espec, $output, true);
-          break;
-        }
-      }
-    }
-    if ($set) {
-      $xfer += $output->writeSetEnd();
-    } else {
-      $xfer += $output->writeListEnd();
-    }
-
-    return $xfer;
-  }
-
-  protected function _write($class, $spec, $output)
-  {
-    $xfer = 0;
-    $xfer += $output->writeStructBegin($class);
-    foreach ($spec as $fid => $fspec) {
-      $var = $fspec['var'];
-      if ($this->$var !== null) {
-        $ftype = $fspec['type'];
-        $xfer += $output->writeFieldBegin($var, $ftype, $fid);
-        if (isset(TBase::$tmethod[$ftype])) {
-          $func = 'write'.TBase::$tmethod[$ftype];
-          $xfer += $output->$func($this->$var);
-        } else {
-          switch ($ftype) {
-          case TType::STRUCT:
-            $xfer += $this->$var->write($output);
-            break;
-          case TType::MAP:
-            $xfer += $this->_writeMap($this->$var, $fspec, $output);
-            break;
-          case TType::LST:
-            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
-            break;
-          case TType::SET:
-            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
-            break;
-          }
-        }
-        $xfer += $output->writeFieldEnd();
-      }
-    }
-    $xfer += $output->writeFieldStop();
-    $xfer += $output->writeStructEnd();
-
-    return $xfer;
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Factory/TTransportFactory.php b/lib/php/lib/Thrift/Factory/TTransportFactory.php
deleted file mode 100644
index b32b5f4..0000000
--- a/lib/php/lib/Thrift/Factory/TTransportFactory.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-namespace Thrift\Factory;
-
-use Thrift\Transport\TTransport;
-
-class TTransportFactory
-{
-  /**
-   * @static
-   * @param TTransport $transport
-   * @return TTransport
-   */
-  public static function getTransport(TTransport $transport)
-  {
-    return $transport;
-  }
-}
diff --git a/lib/php/lib/Thrift/Protocol/TBinaryProtocol.php b/lib/php/lib/Thrift/Protocol/TBinaryProtocol.php
deleted file mode 100644
index fe6a103..0000000
--- a/lib/php/lib/Thrift/Protocol/TBinaryProtocol.php
+++ /dev/null
@@ -1,453 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.protocol
- */
-
-namespace Thrift\Protocol;
-
-use Thrift\Type\TType;
-use Thrift\Exception\TProtocolException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Binary implementation of the Thrift protocol.
- *
- */
-class TBinaryProtocol extends TProtocol
-{
-  const VERSION_MASK = 0xffff0000;
-  const VERSION_1 = 0x80010000;
-
-  protected $strictRead_ = false;
-  protected $strictWrite_ = true;
-
-  public function __construct($trans, $strictRead=false, $strictWrite=true)
-  {
-    parent::__construct($trans);
-    $this->strictRead_ = $strictRead;
-    $this->strictWrite_ = $strictWrite;
-  }
-
-  public function writeMessageBegin($name, $type, $seqid)
-  {
-    if ($this->strictWrite_) {
-      $version = self::VERSION_1 | $type;
-
-      return
-        $this->writeI32($version) +
-        $this->writeString($name) +
-        $this->writeI32($seqid);
-    } else {
-      return
-        $this->writeString($name) +
-        $this->writeByte($type) +
-        $this->writeI32($seqid);
-    }
-  }
-
-  public function writeMessageEnd()
-  {
-    return 0;
-  }
-
-  public function writeStructBegin($name)
-  {
-    return 0;
-  }
-
-  public function writeStructEnd()
-  {
-    return 0;
-  }
-
-  public function writeFieldBegin($fieldName, $fieldType, $fieldId)
-  {
-    return
-      $this->writeByte($fieldType) +
-      $this->writeI16($fieldId);
-  }
-
-  public function writeFieldEnd()
-  {
-    return 0;
-  }
-
-  public function writeFieldStop()
-  {
-    return
-      $this->writeByte(TType::STOP);
-  }
-
-  public function writeMapBegin($keyType, $valType, $size)
-  {
-    return
-      $this->writeByte($keyType) +
-      $this->writeByte($valType) +
-      $this->writeI32($size);
-  }
-
-  public function writeMapEnd()
-  {
-    return 0;
-  }
-
-  public function writeListBegin($elemType, $size)
-  {
-    return
-      $this->writeByte($elemType) +
-      $this->writeI32($size);
-  }
-
-  public function writeListEnd()
-  {
-    return 0;
-  }
-
-  public function writeSetBegin($elemType, $size)
-  {
-    return
-      $this->writeByte($elemType) +
-      $this->writeI32($size);
-  }
-
-  public function writeSetEnd()
-  {
-    return 0;
-  }
-
-  public function writeBool($value)
-  {
-    $data = pack('c', $value ? 1 : 0);
-    $this->trans_->write($data, 1);
-
-    return 1;
-  }
-
-  public function writeByte($value)
-  {
-    $data = pack('c', $value);
-    $this->trans_->write($data, 1);
-
-    return 1;
-  }
-
-  public function writeI16($value)
-  {
-    $data = pack('n', $value);
-    $this->trans_->write($data, 2);
-
-    return 2;
-  }
-
-  public function writeI32($value)
-  {
-    $data = pack('N', $value);
-    $this->trans_->write($data, 4);
-
-    return 4;
-  }
-
-  public function writeI64($value)
-  {
-    // If we are on a 32bit architecture we have to explicitly deal with
-    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
-    // as signed and any int over 2^31 - 1 as a float
-    if (PHP_INT_SIZE == 4) {
-      $neg = $value < 0;
-
-      if ($neg) {
-        $value *= -1;
-      }
-
-      $hi = (int) ($value / 4294967296);
-      $lo = (int) $value;
-
-      if ($neg) {
-        $hi = ~$hi;
-        $lo = ~$lo;
-        if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
-          $lo = 0;
-          $hi++;
-        } else {
-          $lo++;
-        }
-      }
-      $data = pack('N2', $hi, $lo);
-
-    } else {
-      $hi = $value >> 32;
-      $lo = $value & 0xFFFFFFFF;
-      $data = pack('N2', $hi, $lo);
-    }
-
-    $this->trans_->write($data, 8);
-
-    return 8;
-  }
-
-  public function writeDouble($value)
-  {
-    $data = pack('d', $value);
-    $this->trans_->write(strrev($data), 8);
-
-    return 8;
-  }
-
-  public function writeString($value)
-  {
-    $len = TStringFuncFactory::create()->strlen($value);
-    $result = $this->writeI32($len);
-    if ($len) {
-      $this->trans_->write($value, $len);
-    }
-
-    return $result + $len;
-  }
-
-  public function readMessageBegin(&$name, &$type, &$seqid)
-  {
-    $result = $this->readI32($sz);
-    if ($sz < 0) {
-      $version = (int) ($sz & self::VERSION_MASK);
-      if ($version != (int) self::VERSION_1) {
-        throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
-      }
-      $type = $sz & 0x000000ff;
-      $result +=
-        $this->readString($name) +
-        $this->readI32($seqid);
-    } else {
-      if ($this->strictRead_) {
-        throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
-      } else {
-        // Handle pre-versioned input
-        $name = $this->trans_->readAll($sz);
-        $result +=
-          $sz +
-          $this->readByte($type) +
-          $this->readI32($seqid);
-      }
-    }
-
-    return $result;
-  }
-
-  public function readMessageEnd()
-  {
-    return 0;
-  }
-
-  public function readStructBegin(&$name)
-  {
-    $name = '';
-
-    return 0;
-  }
-
-  public function readStructEnd()
-  {
-    return 0;
-  }
-
-  public function readFieldBegin(&$name, &$fieldType, &$fieldId)
-  {
-    $result = $this->readByte($fieldType);
-    if ($fieldType == TType::STOP) {
-      $fieldId = 0;
-
-      return $result;
-    }
-    $result += $this->readI16($fieldId);
-
-    return $result;
-  }
-
-  public function readFieldEnd()
-  {
-    return 0;
-  }
-
-  public function readMapBegin(&$keyType, &$valType, &$size)
-  {
-    return
-      $this->readByte($keyType) +
-      $this->readByte($valType) +
-      $this->readI32($size);
-  }
-
-  public function readMapEnd()
-  {
-    return 0;
-  }
-
-  public function readListBegin(&$elemType, &$size)
-  {
-    return
-      $this->readByte($elemType) +
-      $this->readI32($size);
-  }
-
-  public function readListEnd()
-  {
-    return 0;
-  }
-
-  public function readSetBegin(&$elemType, &$size)
-  {
-    return
-      $this->readByte($elemType) +
-      $this->readI32($size);
-  }
-
-  public function readSetEnd()
-  {
-    return 0;
-  }
-
-  public function readBool(&$value)
-  {
-    $data = $this->trans_->readAll(1);
-    $arr = unpack('c', $data);
-    $value = $arr[1] == 1;
-
-    return 1;
-  }
-
-  public function readByte(&$value)
-  {
-    $data = $this->trans_->readAll(1);
-    $arr = unpack('c', $data);
-    $value = $arr[1];
-
-    return 1;
-  }
-
-  public function readI16(&$value)
-  {
-    $data = $this->trans_->readAll(2);
-    $arr = unpack('n', $data);
-    $value = $arr[1];
-    if ($value > 0x7fff) {
-      $value = 0 - (($value - 1) ^ 0xffff);
-    }
-
-    return 2;
-  }
-
-  public function readI32(&$value)
-  {
-    $data = $this->trans_->readAll(4);
-    $arr = unpack('N', $data);
-    $value = $arr[1];
-    if ($value > 0x7fffffff) {
-      $value = 0 - (($value - 1) ^ 0xffffffff);
-    }
-
-    return 4;
-  }
-
-  public function readI64(&$value)
-  {
-    $data = $this->trans_->readAll(8);
-
-    $arr = unpack('N2', $data);
-
-    // If we are on a 32bit architecture we have to explicitly deal with
-    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
-    // as signed and any int over 2^31 - 1 as a float
-    if (PHP_INT_SIZE == 4) {
-
-      $hi = $arr[1];
-      $lo = $arr[2];
-      $isNeg = $hi  < 0;
-
-      // Check for a negative
-      if ($isNeg) {
-        $hi = ~$hi & (int) 0xffffffff;
-        $lo = ~$lo & (int) 0xffffffff;
-
-        if ($lo == (int) 0xffffffff) {
-          $hi++;
-          $lo = 0;
-        } else {
-          $lo++;
-        }
-      }
-
-      // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
-      // explicitly below
-
-      if ($hi & (int) 0x80000000) {
-        $hi &= (int) 0x7fffffff;
-        $hi += 0x80000000;
-      }
-
-      if ($lo & (int) 0x80000000) {
-        $lo &= (int) 0x7fffffff;
-        $lo += 0x80000000;
-      }
-
-      $value = $hi * 4294967296 + $lo;
-
-      if ($isNeg) {
-        $value = 0 - $value;
-      }
-    } else {
-
-      // Upcast negatives in LSB bit
-      if ($arr[2] & 0x80000000) {
-        $arr[2] = $arr[2] & 0xffffffff;
-      }
-
-      // Check for a negative
-      if ($arr[1] & 0x80000000) {
-        $arr[1] = $arr[1] & 0xffffffff;
-        $arr[1] = $arr[1] ^ 0xffffffff;
-        $arr[2] = $arr[2] ^ 0xffffffff;
-        $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
-      } else {
-        $value = $arr[1]*4294967296 + $arr[2];
-      }
-    }
-
-    return 8;
-  }
-
-  public function readDouble(&$value)
-  {
-    $data = strrev($this->trans_->readAll(8));
-    $arr = unpack('d', $data);
-    $value = $arr[1];
-
-    return 8;
-  }
-
-  public function readString(&$value)
-  {
-    $result = $this->readI32($len);
-    if ($len) {
-      $value = $this->trans_->readAll($len);
-    } else {
-      $value = '';
-    }
-
-    return $result + $len;
-  }
-}
diff --git a/lib/php/lib/Thrift/Protocol/TBinaryProtocolAccelerated.php b/lib/php/lib/Thrift/Protocol/TBinaryProtocolAccelerated.php
deleted file mode 100644
index f0e0bb9..0000000
--- a/lib/php/lib/Thrift/Protocol/TBinaryProtocolAccelerated.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.protocol
- */
-
-namespace Thrift\Protocol;
-
-use Thrift\Transport\TBufferedTransport;
-
-/**
- * Accelerated binary protocol: used in conjunction with the thrift_protocol
- * extension for faster deserialization
- */
-class TBinaryProtocolAccelerated extends TBinaryProtocol
-{
-  public function __construct($trans, $strictRead=false, $strictWrite=true)
-  {
-    // If the transport doesn't implement putBack, wrap it in a
-    // TBufferedTransport (which does)
-
-    // NOTE (t.heintz): This is very evil to do, because the TBufferedTransport may swallow bytes, which
-    // are then never written to the underlying transport. This happens precisely when a number of bytes
-    // less than the max buffer size (512 by default) is written to the transport and then flush() is NOT
-    // called. In that case the data stays in the writeBuffer of the transport, from where it can never be
-    // accessed again (for example through read()).
-    //
-    // Since the caller of this method does not know about the wrapping transport, this creates bugs which
-    // are very difficult to find. Hence the wrapping of a transport in a buffer should be left to the
-    // calling code. An interface could used to mandate the presence of the putBack() method in the transport.
-    //
-    // I am leaving this code in nonetheless, because there may be applications depending on this behavior.
-    //
-    // @see THRIFT-1579
-
-    if (!method_exists($trans, 'putBack')) {
-      $trans = new TBufferedTransport($trans);
-    }
-    parent::__construct($trans, $strictRead, $strictWrite);
-  }
-  public function isStrictRead()
-  {
-    return $this->strictRead_;
-  }
-  public function isStrictWrite()
-  {
-    return $this->strictWrite_;
-  }
-}
diff --git a/lib/php/lib/Thrift/Protocol/TCompactProtocol.php b/lib/php/lib/Thrift/Protocol/TCompactProtocol.php
deleted file mode 100644
index c25b050..0000000
--- a/lib/php/lib/Thrift/Protocol/TCompactProtocol.php
+++ /dev/null
@@ -1,739 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.protocol
- */
-
-namespace Thrift\Protocol;
-
-use Thrift\Type\TType;
-use Thrift\Exception\TProtocolException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Compact implementation of the Thrift protocol.
- *
- */
-class TCompactProtocol extends TProtocol
-{
-  const COMPACT_STOP = 0x00;
-  const COMPACT_TRUE = 0x01;
-  const COMPACT_FALSE = 0x02;
-  const COMPACT_BYTE = 0x03;
-  const COMPACT_I16 = 0x04;
-  const COMPACT_I32 = 0x05;
-  const COMPACT_I64 = 0x06;
-  const COMPACT_DOUBLE = 0x07;
-  const COMPACT_BINARY = 0x08;
-  const COMPACT_LIST = 0x09;
-  const COMPACT_SET = 0x0A;
-  const COMPACT_MAP = 0x0B;
-  const COMPACT_STRUCT = 0x0C;
-
-  const STATE_CLEAR = 0;
-  const STATE_FIELD_WRITE = 1;
-  const STATE_VALUE_WRITE = 2;
-  const STATE_CONTAINER_WRITE = 3;
-  const STATE_BOOL_WRITE = 4;
-  const STATE_FIELD_READ = 5;
-  const STATE_CONTAINER_READ = 6;
-  const STATE_VALUE_READ = 7;
-  const STATE_BOOL_READ = 8;
-
-  const VERSION_MASK = 0x1f;
-  const VERSION = 1;
-  const PROTOCOL_ID = 0x82;
-  const TYPE_MASK = 0xe0;
-  const TYPE_BITS = 0x07;
-  const TYPE_SHIFT_AMOUNT = 5;
-
-  protected static $ctypes = array(
-    TType::STOP => TCompactProtocol::COMPACT_STOP,
-    TType::BOOL => TCompactProtocol::COMPACT_TRUE, // used for collection
-    TType::BYTE => TCompactProtocol::COMPACT_BYTE,
-    TType::I16 => TCompactProtocol::COMPACT_I16,
-    TType::I32 => TCompactProtocol::COMPACT_I32,
-    TType::I64 => TCompactProtocol::COMPACT_I64,
-    TType::DOUBLE => TCompactProtocol::COMPACT_DOUBLE,
-    TType::STRING => TCompactProtocol::COMPACT_BINARY,
-    TType::STRUCT => TCompactProtocol::COMPACT_STRUCT,
-    TType::LST => TCompactProtocol::COMPACT_LIST,
-    TType::SET => TCompactProtocol::COMPACT_SET,
-    TType::MAP => TCompactProtocol::COMPACT_MAP,
-  );
-
-  protected static $ttypes = array(
-    TCompactProtocol::COMPACT_STOP => TType::STOP ,
-    TCompactProtocol::COMPACT_TRUE => TType::BOOL, // used for collection
-    TCompactProtocol::COMPACT_FALSE => TType::BOOL,
-    TCompactProtocol::COMPACT_BYTE => TType::BYTE,
-    TCompactProtocol::COMPACT_I16 => TType::I16,
-    TCompactProtocol::COMPACT_I32 => TType::I32,
-    TCompactProtocol::COMPACT_I64 => TType::I64,
-    TCompactProtocol::COMPACT_DOUBLE => TType::DOUBLE,
-    TCompactProtocol::COMPACT_BINARY => TType::STRING,
-    TCompactProtocol::COMPACT_STRUCT => TType::STRUCT,
-    TCompactProtocol::COMPACT_LIST => TType::LST,
-    TCompactProtocol::COMPACT_SET => TType::SET,
-    TCompactProtocol::COMPACT_MAP => TType::MAP,
-  );
-
-  protected $state = TCompactProtocol::STATE_CLEAR;
-  protected $lastFid = 0;
-  protected $boolFid = null;
-  protected $boolValue = null;
-  protected $structs = array();
-  protected $containers = array();
-
-  // Some varint / zigzag helper methods
-  public function toZigZag($n, $bits)
-  {
-    return ($n << 1) ^ ($n >> ($bits - 1));
-  }
-
-  public function fromZigZag($n)
-  {
-    return ($n >> 1) ^ -($n & 1);
-  }
-
-  public function getVarint($data)
-  {
-    $out = "";
-    while (true) {
-      if (($data & ~0x7f) === 0) {
-        $out .= chr($data);
-        break;
-      } else {
-        $out .= chr(($data & 0xff) | 0x80);
-        $data = $data >> 7;
-      }
-    }
-
-    return $out;
-  }
-
-  public function writeVarint($data)
-  {
-    $out = $this->getVarint($data);
-    $result = TStringFuncFactory::create()->strlen($out);
-    $this->trans_->write($out, $result);
-
-    return $result;
-  }
-
-  public function readVarint(&$result)
-  {
-    $idx = 0;
-    $shift = 0;
-    $result = 0;
-    while (true) {
-      $x = $this->trans_->readAll(1);
-      $arr = unpack('C', $x);
-      $byte = $arr[1];
-      $idx += 1;
-      $result |= ($byte & 0x7f) << $shift;
-      if (($byte >> 7) === 0) {
-        return $idx;
-      }
-      $shift += 7;
-    }
-
-    return $idx;
-  }
-
-  public function __construct($trans)
-  {
-    parent::__construct($trans);
-  }
-
-  public function writeMessageBegin($name, $type, $seqid)
-  {
-    $written =
-      $this->writeUByte(TCompactProtocol::PROTOCOL_ID) +
-      $this->writeUByte(TCompactProtocol::VERSION |
-                        ($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)) +
-      $this->writeVarint($seqid) +
-      $this->writeString($name);
-    $this->state = TCompactProtocol::STATE_VALUE_WRITE;
-
-    return $written;
-  }
-
-  public function writeMessageEnd()
-  {
-    $this->state = TCompactProtocol::STATE_CLEAR;
-
-    return 0;
-  }
-
-  public function writeStructBegin($name)
-  {
-    $this->structs[] = array($this->state, $this->lastFid);
-    $this->state = TCompactProtocol::STATE_FIELD_WRITE;
-    $this->lastFid = 0;
-
-    return 0;
-  }
-
-  public function writeStructEnd()
-  {
-    $old_values = array_pop($this->structs);
-    $this->state = $old_values[0];
-    $this->lastFid = $old_values[1];
-
-    return 0;
-  }
-
-  public function writeFieldStop()
-  {
-    return $this->writeByte(0);
-  }
-
-  public function writeFieldHeader($type, $fid)
-  {
-    $written = 0;
-    $delta = $fid - $this->lastFid;
-    if (0 < $delta && $delta <= 15) {
-      $written = $this->writeUByte(($delta << 4) | $type);
-    } else {
-      $written = $this->writeByte($type) +
-        $this->writeI16($fid);
-    }
-    $this->lastFid = $fid;
-
-    return $written;
-  }
-
-  public function writeFieldBegin($field_name, $field_type, $field_id)
-  {
-    if ($field_type == TTYPE::BOOL) {
-      $this->state = TCompactProtocol::STATE_BOOL_WRITE;
-      $this->boolFid = $field_id;
-
-      return 0;
-    } else {
-      $this->state = TCompactProtocol::STATE_VALUE_WRITE;
-
-      return $this->writeFieldHeader(self::$ctypes[$field_type], $field_id);
-    }
-  }
-
-  public function writeFieldEnd()
-  {
-    $this->state = TCompactProtocol::STATE_FIELD_WRITE;
-
-    return 0;
-  }
-
-  public function writeCollectionBegin($etype, $size)
-  {
-    $written = 0;
-    if ($size <= 14) {
-      $written = $this->writeUByte($size << 4 |
-                                    self::$ctypes[$etype]);
-    } else {
-      $written = $this->writeUByte(0xf0 |
-                                   self::$ctypes[$etype]) +
-        $this->writeVarint($size);
-    }
-    $this->containers[] = $this->state;
-    $this->state = TCompactProtocol::STATE_CONTAINER_WRITE;
-
-    return $written;
-  }
-
-  public function writeMapBegin($key_type, $val_type, $size)
-  {
-    $written = 0;
-    if ($size == 0) {
-      $written = $this->writeByte(0);
-    } else {
-      $written = $this->writeVarint($size) +
-        $this->writeUByte(self::$ctypes[$key_type] << 4 |
-                          self::$ctypes[$val_type]);
-    }
-    $this->containers[] = $this->state;
-
-    return $written;
-  }
-
-  public function writeCollectionEnd()
-  {
-    $this->state = array_pop($this->containers);
-
-    return 0;
-  }
-
-  public function writeMapEnd()
-  {
-    return $this->writeCollectionEnd();
-  }
-
-  public function writeListBegin($elem_type, $size)
-  {
-    return $this->writeCollectionBegin($elem_type, $size);
-  }
-
-  public function writeListEnd()
-  {
-    return $this->writeCollectionEnd();
-  }
-
-  public function writeSetBegin($elem_type, $size)
-  {
-    return $this->writeCollectionBegin($elem_type, $size);
-  }
-
-  public function writeSetEnd()
-  {
-    return $this->writeCollectionEnd();
-  }
-
-  public function writeBool($value)
-  {
-    if ($this->state == TCompactProtocol::STATE_BOOL_WRITE) {
-      $ctype = TCompactProtocol::COMPACT_FALSE;
-      if ($value) {
-        $ctype = TCompactProtocol::COMPACT_TRUE;
-      }
-
-      return $this->writeFieldHeader($ctype, $this->boolFid);
-    } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_WRITE) {
-      return $this->writeByte($value ? 1 : 0);
-    } else {
-      throw new TProtocolException('Invalid state in compact protocol');
-    }
-  }
-
-  public function writeByte($value)
-  {
-    $data = pack('c', $value);
-    $this->trans_->write($data, 1);
-
-    return 1;
-  }
-
-  public function writeUByte($byte)
-  {
-    $this->trans_->write(pack('C', $byte), 1);
-
-    return 1;
-  }
-
-  public function writeI16($value)
-  {
-    $thing = $this->toZigZag($value, 16);
-
-    return $this->writeVarint($thing);
-  }
-
-  public function writeI32($value)
-  {
-    $thing = $this->toZigZag($value, 32);
-
-    return $this->writeVarint($thing);
-  }
-
-  public function writeDouble($value)
-  {
-    $data = pack('d', $value);
-    $this->trans_->write($data, 8);
-
-    return 8;
-  }
-
-  public function writeString($value)
-  {
-    $len = TStringFuncFactory::create()->strlen($value);
-    $result = $this->writeVarint($len);
-    if ($len) {
-      $this->trans_->write($value, $len);
-    }
-
-    return $result + $len;
-  }
-
-  public function readFieldBegin(&$name, &$field_type, &$field_id)
-  {
-    $result = $this->readUByte($compact_type_and_delta);
-
-    $compact_type = $compact_type_and_delta & 0x0f;
-
-    if ($compact_type == TType::STOP) {
-      $field_type = $compact_type;
-      $field_id = 0;
-
-      return $result;
-    }
-    $delta = $compact_type_and_delta >> 4;
-    if ($delta == 0) {
-      $result += $this->readI16($field_id);
-    } else {
-      $field_id = $this->lastFid + $delta;
-    }
-    $this->lastFid = $field_id;
-    $field_type = $this->getTType($compact_type);
-
-    if ($compact_type == TCompactProtocol::COMPACT_TRUE) {
-      $this->state = TCompactProtocol::STATE_BOOL_READ;
-      $this->boolValue = true;
-    } elseif ($compact_type == TCompactProtocol::COMPACT_FALSE) {
-      $this->state = TCompactProtocol::STATE_BOOL_READ;
-      $this->boolValue = false;
-    } else {
-      $this->state = TCompactProtocol::STATE_VALUE_READ;
-    }
-
-    return $result;
-  }
-
-  public function readFieldEnd()
-  {
-    $this->state = TCompactProtocol::STATE_FIELD_READ;
-
-    return 0;
-  }
-
-  public function readUByte(&$value)
-  {
-    $data = $this->trans_->readAll(1);
-    $arr = unpack('C', $data);
-    $value = $arr[1];
-
-    return 1;
-  }
-
-  public function readByte(&$value)
-  {
-    $data = $this->trans_->readAll(1);
-    $arr = unpack('c', $data);
-    $value = $arr[1];
-
-    return 1;
-  }
-
-  public function readZigZag(&$value)
-  {
-    $result = $this->readVarint($value);
-    $value = $this->fromZigZag($value);
-
-    return $result;
-  }
-
-  public function readMessageBegin(&$name, &$type, &$seqid)
-  {
-    $protoId = 0;
-    $result = $this->readUByte($protoId);
-    if ($protoId != TCompactProtocol::PROTOCOL_ID) {
-      throw new TProtocolException('Bad protocol id in TCompact message');
-    }
-    $verType = 0;
-    $result += $this->readUByte($verType);
-    $type = ($verType >> TCompactProtocol::TYPE_SHIFT_AMOUNT) & TCompactProtocol::TYPE_BITS;
-    $version = $verType & TCompactProtocol::VERSION_MASK;
-    if ($version != TCompactProtocol::VERSION) {
-      throw new TProtocolException('Bad version in TCompact message');
-    }
-    $result += $this->readVarint($seqid);
-    $result += $this->readString($name);
-
-    return $result;
-  }
-
-  public function readMessageEnd()
-  {
-    return 0;
-  }
-
-  public function readStructBegin(&$name)
-  {
-    $name = ''; // unused
-    $this->structs[] = array($this->state, $this->lastFid);
-    $this->state = TCompactProtocol::STATE_FIELD_READ;
-    $this->lastFid = 0;
-
-    return 0;
-  }
-
-  public function readStructEnd()
-  {
-    $last = array_pop($this->structs);
-    $this->state = $last[0];
-    $this->lastFid = $last[1];
-
-    return 0;
-  }
-
-  public function readCollectionBegin(&$type, &$size)
-  {
-    $sizeType = 0;
-    $result = $this->readUByte($sizeType);
-    $size = $sizeType >> 4;
-    $type = $this->getTType($sizeType);
-    if ($size == 15) {
-      $result += $this->readVarint($size);
-    }
-    $this->containers[] = $this->state;
-    $this->state = TCompactProtocol::STATE_CONTAINER_READ;
-
-    return $result;
-  }
-
-  public function readMapBegin(&$key_type, &$val_type, &$size)
-  {
-    $result = $this->readVarint($size);
-    $types = 0;
-    if ($size > 0) {
-      $result += $this->readUByte($types);
-    }
-    $val_type = $this->getTType($types);
-    $key_type = $this->getTType($types >> 4);
-    $this->containers[] = $this->state;
-    $this->state = TCompactProtocol::STATE_CONTAINER_READ;
-
-    return $result;
-  }
-
-  public function readCollectionEnd()
-  {
-    $this->state = array_pop($this->containers);
-
-    return 0;
-  }
-
-  public function readMapEnd()
-  {
-    return $this->readCollectionEnd();
-  }
-
-  public function readListBegin(&$elem_type, &$size)
-  {
-    return $this->readCollectionBegin($elem_type, $size);
-  }
-
-  public function readListEnd()
-  {
-    return $this->readCollectionEnd();
-  }
-
-  public function readSetBegin(&$elem_type, &$size)
-  {
-    return $this->readCollectionBegin($elem_type, $size);
-  }
-
-  public function readSetEnd()
-  {
-    return $this->readCollectionEnd();
-  }
-
-  public function readBool(&$value)
-  {
-    if ($this->state == TCompactProtocol::STATE_BOOL_READ) {
-      $value = $this->boolValue;
-
-      return 0;
-    } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_READ) {
-      return $this->readByte($value);
-    } else {
-      throw new TProtocolException('Invalid state in compact protocol');
-    }
-  }
-
-  public function readI16(&$value)
-  {
-    return $this->readZigZag($value);
-  }
-
-  public function readI32(&$value)
-  {
-    return $this->readZigZag($value);
-  }
-
-  public function readDouble(&$value)
-  {
-    $data = $this->trans_->readAll(8);
-    $arr = unpack('d', $data);
-    $value = $arr[1];
-
-    return 8;
-  }
-
-  public function readString(&$value)
-  {
-    $result = $this->readVarint($len);
-    if ($len) {
-      $value = $this->trans_->readAll($len);
-    } else {
-      $value = '';
-    }
-
-    return $result + $len;
-  }
-
-  public function getTType($byte)
-  {
-    return self::$ttypes[$byte & 0x0f];
-  }
-
-  // If we are on a 32bit architecture we have to explicitly deal with
-  // 64-bit twos-complement arithmetic since PHP wants to treat all ints
-  // as signed and any int over 2^31 - 1 as a float
-
-  // Read and write I64 as two 32 bit numbers $hi and $lo
-
-  public function readI64(&$value)
-  {
-    // Read varint from wire
-    $hi = 0;
-    $lo = 0;
-
-    $idx = 0;
-    $shift = 0;
-
-    while (true) {
-      $x = $this->trans_->readAll(1);
-      $arr = unpack('C', $x);
-      $byte = $arr[1];
-      $idx += 1;
-      // Shift hi and lo together.
-      if ($shift < 28) {
-        $lo |= (($byte & 0x7f) << $shift);
-      } elseif ($shift == 28) {
-        $lo |= (($byte & 0x0f) << 28);
-        $hi |= (($byte & 0x70) >> 4);
-      } else {
-        $hi |= (($byte & 0x7f) << ($shift - 32));
-      }
-      if (($byte >> 7) === 0) {
-        break;
-      }
-      $shift += 7;
-    }
-
-    // Now, unzig it.
-    $xorer = 0;
-    if ($lo & 1) {
-      $xorer = 0xffffffff;
-    }
-    $lo = ($lo >> 1) & 0x7fffffff;
-    $lo = $lo | (($hi & 1) << 31);
-    $hi = ($hi >> 1) ^ $xorer;
-    $lo = $lo ^ $xorer;
-
-    // Now put $hi and $lo back together
-    $isNeg = $hi < 0 || $hi & 0x80000000;
-
-    // Check for a negative
-    if ($isNeg) {
-      $hi = ~$hi & (int) 0xffffffff;
-      $lo = ~$lo & (int) 0xffffffff;
-
-      if ($lo == (int) 0xffffffff) {
-        $hi++;
-        $lo = 0;
-      } else {
-        $lo++;
-      }
-    }
-
-    // Force 32bit words in excess of 2G to be positive - we deal with sign
-    // explicitly below
-
-    if ($hi & (int) 0x80000000) {
-      $hi &= (int) 0x7fffffff;
-      $hi += 0x80000000;
-    }
-
-    if ($lo & (int) 0x80000000) {
-      $lo &= (int) 0x7fffffff;
-      $lo += 0x80000000;
-    }
-
-    // Create as negative value first, since we can store -2^63 but not 2^63
-    $value = -$hi * 4294967296 - $lo;
-
-    if (!$isNeg) {
-      $value = -$value;
-    }
-
-    return $idx;
-  }
-
-  public function writeI64($value)
-  {
-    // If we are in an I32 range, use the easy method below.
-    if (($value > 4294967296) || ($value < -4294967296)) {
-      // Convert $value to $hi and $lo
-      $neg = $value < 0;
-
-      if ($neg) {
-        $value *= -1;
-      }
-
-      $hi = (int) $value >> 32;
-      $lo = (int) $value & 0xffffffff;
-
-      if ($neg) {
-        $hi = ~$hi;
-        $lo = ~$lo;
-        if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
-          $lo = 0;
-          $hi++;
-        } else {
-          $lo++;
-        }
-      }
-
-      // Now do the zigging and zagging.
-      $xorer = 0;
-      if ($neg) {
-        $xorer = 0xffffffff;
-      }
-      $lowbit = ($lo >> 31) & 1;
-      $hi = ($hi << 1) | $lowbit;
-      $lo = ($lo << 1);
-      $lo = ($lo ^ $xorer) & 0xffffffff;
-      $hi = ($hi ^ $xorer) & 0xffffffff;
-
-      // now write out the varint, ensuring we shift both hi and lo
-      $out = "";
-      while (true) {
-        if (($lo & ~0x7f) === 0 &&
-           $hi === 0) {
-          $out .= chr($lo);
-          break;
-        } else {
-          $out .= chr(($lo & 0xff) | 0x80);
-          $lo = $lo >> 7;
-          $lo = $lo | ($hi << 25);
-          $hi = $hi >> 7;
-          // Right shift carries sign, but we don't want it to.
-          $hi = $hi & (127 << 25);
-        }
-      }
-
-      $ret = TStringFuncFactory::create()->strlen($out);
-      $this->trans_->write($out, $ret);
-
-      return $ret;
-    } else {
-      return $this->writeVarint($this->toZigZag($value, 64));
-    }
-  }
-}
diff --git a/lib/php/lib/Thrift/Protocol/TProtocol.php b/lib/php/lib/Thrift/Protocol/TProtocol.php
deleted file mode 100644
index 0e3bc0d..0000000
--- a/lib/php/lib/Thrift/Protocol/TProtocol.php
+++ /dev/null
@@ -1,352 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.protocol
- */
-
-namespace Thrift\Protocol;
-
-use Thrift\Type\TType;
-use Thrift\Exception\TProtocolException;
-
-/**
- * Protocol base class module.
- */
-abstract class TProtocol
-{
-  /**
-   * Underlying transport
-   *
-   * @var TTransport
-   */
-  protected $trans_;
-
-  /**
-   * Constructor
-   */
-  protected function __construct($trans)
-  {
-    $this->trans_ = $trans;
-  }
-
-  /**
-   * Accessor for transport
-   *
-   * @return TTransport
-   */
-  public function getTransport()
-  {
-    return $this->trans_;
-  }
-
-  /**
-   * Writes the message header
-   *
-   * @param string $name Function name
-   * @param int $type message type TMessageType::CALL or TMessageType::REPLY
-   * @param int $seqid The sequence id of this message
-   */
-  abstract public function writeMessageBegin($name, $type, $seqid);
-
-  /**
-   * Close the message
-   */
-  abstract public function writeMessageEnd();
-
-  /**
-   * Writes a struct header.
-   *
-   * @param string     $name Struct name
-   * @throws TException on write error
-   * @return int How many bytes written
-   */
-  abstract public function writeStructBegin($name);
-
-  /**
-   * Close a struct.
-   *
-   * @throws TException on write error
-   * @return int How many bytes written
-   */
-  abstract public function writeStructEnd();
-
-  /*
-   * Starts a field.
-   *
-   * @param string     $name Field name
-   * @param int        $type Field type
-   * @param int        $fid  Field id
-   * @throws TException on write error
-   * @return int How many bytes written
-   */
-  abstract public function writeFieldBegin($fieldName, $fieldType, $fieldId);
-
-  abstract public function writeFieldEnd();
-
-  abstract public function writeFieldStop();
-
-  abstract public function writeMapBegin($keyType, $valType, $size);
-
-  abstract public function writeMapEnd();
-
-  abstract public function writeListBegin($elemType, $size);
-
-  abstract public function writeListEnd();
-
-  abstract public function writeSetBegin($elemType, $size);
-
-  abstract public function writeSetEnd();
-
-  abstract public function writeBool($bool);
-
-  abstract public function writeByte($byte);
-
-  abstract public function writeI16($i16);
-
-  abstract public function writeI32($i32);
-
-  abstract public function writeI64($i64);
-
-  abstract public function writeDouble($dub);
-
-  abstract public function writeString($str);
-
-  /**
-   * Reads the message header
-   *
-   * @param string $name Function name
-   * @param int $type message type TMessageType::CALL or TMessageType::REPLY
-   * @parem int $seqid The sequence id of this message
-   */
-  abstract public function readMessageBegin(&$name, &$type, &$seqid);
-
-  /**
-   * Read the close of message
-   */
-  abstract public function readMessageEnd();
-
-  abstract public function readStructBegin(&$name);
-
-  abstract public function readStructEnd();
-
-  abstract public function readFieldBegin(&$name, &$fieldType, &$fieldId);
-
-  abstract public function readFieldEnd();
-
-  abstract public function readMapBegin(&$keyType, &$valType, &$size);
-
-  abstract public function readMapEnd();
-
-  abstract public function readListBegin(&$elemType, &$size);
-
-  abstract public function readListEnd();
-
-  abstract public function readSetBegin(&$elemType, &$size);
-
-  abstract public function readSetEnd();
-
-  abstract public function readBool(&$bool);
-
-  abstract public function readByte(&$byte);
-
-  abstract public function readI16(&$i16);
-
-  abstract public function readI32(&$i32);
-
-  abstract public function readI64(&$i64);
-
-  abstract public function readDouble(&$dub);
-
-  abstract public function readString(&$str);
-
-  /**
-   * The skip function is a utility to parse over unrecognized date without
-   * causing corruption.
-   *
-   * @param TType $type What type is it
-   */
-  public function skip($type)
-  {
-    switch ($type) {
-    case TType::BOOL:
-      return $this->readBool($bool);
-    case TType::BYTE:
-      return $this->readByte($byte);
-    case TType::I16:
-      return $this->readI16($i16);
-    case TType::I32:
-      return $this->readI32($i32);
-    case TType::I64:
-      return $this->readI64($i64);
-    case TType::DOUBLE:
-      return $this->readDouble($dub);
-    case TType::STRING:
-      return $this->readString($str);
-    case TType::STRUCT:
-      {
-        $result = $this->readStructBegin($name);
-        while (true) {
-          $result += $this->readFieldBegin($name, $ftype, $fid);
-          if ($ftype == TType::STOP) {
-            break;
-          }
-          $result += $this->skip($ftype);
-          $result += $this->readFieldEnd();
-        }
-        $result += $this->readStructEnd();
-
-        return $result;
-      }
-    case TType::MAP:
-      {
-        $result = $this->readMapBegin($keyType, $valType, $size);
-        for ($i = 0; $i < $size; $i++) {
-          $result += $this->skip($keyType);
-          $result += $this->skip($valType);
-        }
-        $result += $this->readMapEnd();
-
-        return $result;
-      }
-    case TType::SET:
-      {
-        $result = $this->readSetBegin($elemType, $size);
-        for ($i = 0; $i < $size; $i++) {
-          $result += $this->skip($elemType);
-        }
-        $result += $this->readSetEnd();
-
-        return $result;
-      }
-    case TType::LST:
-      {
-        $result = $this->readListBegin($elemType, $size);
-        for ($i = 0; $i < $size; $i++) {
-          $result += $this->skip($elemType);
-        }
-        $result += $this->readListEnd();
-
-        return $result;
-      }
-    default:
-      throw new TProtocolException('Unknown field type: '.$type,
-                                   TProtocolException::INVALID_DATA);
-    }
-  }
-
-  /**
-   * Utility for skipping binary data
-   *
-   * @param TTransport $itrans TTransport object
-   * @param int        $type   Field type
-   */
-  public static function skipBinary($itrans, $type)
-  {
-    switch ($type) {
-    case TType::BOOL:
-      return $itrans->readAll(1);
-    case TType::BYTE:
-      return $itrans->readAll(1);
-    case TType::I16:
-      return $itrans->readAll(2);
-    case TType::I32:
-      return $itrans->readAll(4);
-    case TType::I64:
-      return $itrans->readAll(8);
-    case TType::DOUBLE:
-      return $itrans->readAll(8);
-    case TType::STRING:
-      $len = unpack('N', $itrans->readAll(4));
-      $len = $len[1];
-      if ($len > 0x7fffffff) {
-        $len = 0 - (($len - 1) ^ 0xffffffff);
-      }
-
-      return 4 + $itrans->readAll($len);
-    case TType::STRUCT:
-      {
-        $result = 0;
-        while (true) {
-          $ftype = 0;
-          $fid = 0;
-          $data = $itrans->readAll(1);
-          $arr = unpack('c', $data);
-          $ftype = $arr[1];
-          if ($ftype == TType::STOP) {
-            break;
-          }
-          // I16 field id
-          $result += $itrans->readAll(2);
-          $result += self::skipBinary($itrans, $ftype);
-        }
-
-        return $result;
-      }
-    case TType::MAP:
-      {
-        // Ktype
-        $data = $itrans->readAll(1);
-        $arr = unpack('c', $data);
-        $ktype = $arr[1];
-        // Vtype
-        $data = $itrans->readAll(1);
-        $arr = unpack('c', $data);
-        $vtype = $arr[1];
-        // Size
-        $data = $itrans->readAll(4);
-        $arr = unpack('N', $data);
-        $size = $arr[1];
-        if ($size > 0x7fffffff) {
-          $size = 0 - (($size - 1) ^ 0xffffffff);
-        }
-        $result = 6;
-        for ($i = 0; $i < $size; $i++) {
-          $result += self::skipBinary($itrans, $ktype);
-          $result += self::skipBinary($itrans, $vtype);
-        }
-
-        return $result;
-      }
-    case TType::SET:
-    case TType::LST:
-      {
-        // Vtype
-        $data = $itrans->readAll(1);
-        $arr = unpack('c', $data);
-        $vtype = $arr[1];
-        // Size
-        $data = $itrans->readAll(4);
-        $arr = unpack('N', $data);
-        $size = $arr[1];
-        if ($size > 0x7fffffff) {
-          $size = 0 - (($size - 1) ^ 0xffffffff);
-        }
-        $result = 5;
-        for ($i = 0; $i < $size; $i++) {
-          $result += self::skipBinary($itrans, $vtype);
-        }
-
-        return $result;
-      }
-    default:
-      throw new TProtocolException('Unknown field type: '.$type,
-                                   TProtocolException::INVALID_DATA);
-    }
-  }
-}
diff --git a/lib/php/lib/Thrift/Serializer/TBinarySerializer.php b/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
deleted file mode 100644
index aa2f71b..0000000
--- a/lib/php/lib/Thrift/Serializer/TBinarySerializer.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.protocol
- * @author: rmarin (marin.radu@facebook.com)
- */
-
-namespace Thrift\Serializer;
-
-use Thrift\Transport\TMemoryBuffer;
-use Thrift\Protocol\TBinaryProtocolAccelerated;
-use Thrift\Type\TMessageType;
-
-/**
- * Utility class for serializing and deserializing
- * a thrift object using TBinaryProtocolAccelerated.
- */
-class TBinarySerializer
-{
-  // NOTE(rmarin): Because thrift_protocol_write_binary
-  // adds a begin message prefix, you cannot specify
-  // a transport in which to serialize an object. It has to
-  // be a string. Otherwise we will break the compatibility with
-  // normal deserialization.
-  public static function serialize($object)
-  {
-    $transport = new TMemoryBuffer();
-    $protocol = new TBinaryProtocolAccelerated($transport);
-    if (function_exists('thrift_protocol_write_binary')) {
-      thrift_protocol_write_binary($protocol, $object->getName(),
-                                   TMessageType::REPLY, $object,
-                                   0, $protocol->isStrictWrite());
-
-      $protocol->readMessageBegin($unused_name, $unused_type,
-                                  $unused_seqid);
-    } else {
-      $object->write($protocol);
-    }
-    $protocol->getTransport()->flush();
-
-    return $transport->getBuffer();
-  }
-
-  public static function deserialize($string_object, $class_name, $buffer_size  = 8192)
-  {
-     $transport = new TMemoryBuffer();
-     $protocol = new TBinaryProtocolAccelerated($transport);
-     if (function_exists('thrift_protocol_read_binary')) {
-       // NOTE (t.heintz) TBinaryProtocolAccelerated internally wraps our TMemoryBuffer in a
-       // TBufferedTransport, so we have to retrieve it again or risk losing data when writing
-       // less than 512 bytes to the transport (see the comment there as well).
-       // @see THRIFT-1579
-       $protocol->writeMessageBegin('', TMessageType::REPLY, 0);
-       $protocolTransport = $protocol->getTransport();
-       $protocolTransport->write($string_object);
-       $protocolTransport->flush();
-
-       return thrift_protocol_read_binary($protocol, $class_name,
-                                          $protocol->isStrictRead(),
-                                          $buffer_size);
-     } else {
-       $transport->write($string_object);
-       $object = new $class_name();
-       $object->read($protocol);
-
-       return $object;
-     }
-  }
-}
diff --git a/lib/php/lib/Thrift/Server/TForkingServer.php b/lib/php/lib/Thrift/Server/TForkingServer.php
deleted file mode 100644
index 7f6e541..0000000
--- a/lib/php/lib/Thrift/Server/TForkingServer.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-
-namespace Thrift\Server;
-
-use Thrift\Transport\TTransport;
-use Thrift\Exception\TException;
-use Thrift\Exception\TTransportException;
-
-/**
- * A forking implementation of a Thrift server.
- *
- * @package thrift.server
- */
-class TForkingServer extends TServer
-{
-  /**
-   * Flag for the main serving loop
-   *
-   * @var bool
-   */
-  private $stop_ = false;
-
-  /**
-   * List of children.
-   *
-   * @var array
-   */
-  protected $children_ = array();
-
-  /**
-   * Listens for new client using the supplied
-   * transport. We fork when a new connection
-   * arrives.
-   *
-   * @return void
-   */
-  public function serve()
-  {
-    $this->transport_->listen();
-
-    while (!$this->stop_) {
-      try {
-        $transport = $this->transport_->accept();
-
-        if ($transport != null) {
-          $pid = pcntl_fork();
-
-          if ($pid > 0) {
-            $this->handleParent($transport, $pid);
-          } elseif ($pid === 0) {
-            $this->handleChild($transport);
-          } else {
-            throw new TException('Failed to fork');
-          }
-        }
-      } catch (TTransportException $e) { }
-
-      $this->collectChildren();
-    }
-  }
-
-  /**
-   * Code run by the parent
-   *
-   * @param TTransport $transport
-   * @param int $pid
-   * @return void
-   */
-  private function handleParent(TTransport $transport, $pid)
-  {
-    $this->children_[$pid] = $transport;
-  }
-
-  /**
-   * Code run by the child.
-   *
-   * @param TTransport $transport
-   * @return void
-   */
-  private function handleChild(TTransport $transport)
-  {
-    try {
-      $inputTransport = $this->inputTransportFactory_->getTransport($transport);
-      $outputTransport = $this->outputTransportFactory_->getTransport($transport);
-      $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
-      $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
-      while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
-      @$transport->close();
-    } catch (TTransportException $e) { }
-
-    exit(0);
-  }
-
-  /**
-   * Collects any children we may have
-   *
-   * @return void
-   */
-  private function collectChildren()
-  {
-    foreach ($this->children_ as $pid => $transport) {
-      if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
-        unset($this->children_[$pid]);
-        if ($transport) @$transport->close();
-      }
-    }
-  }
-
-  /**
-   * Stops the server running. Kills the transport
-   * and then stops the main serving loop
-   *
-   * @return void
-   */
-  public function stop()
-  {
-    $this->transport_->close();
-    $this->stop_ = true;
-  }
-}
diff --git a/lib/php/lib/Thrift/Server/TSSLServerSocket.php b/lib/php/lib/Thrift/Server/TSSLServerSocket.php
deleted file mode 100644
index dfc4704..0000000
--- a/lib/php/lib/Thrift/Server/TSSLServerSocket.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/*
- * 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.
- *
- */
-
-namespace Thrift\Server;
-
-use Thrift\Transport\TSSLSocket;
-
-/**
- * Socket implementation of a server agent.
- *
- * @package thrift.transport
- */
-class TSSLServerSocket extends TServerSocket
-{
-  /**
-   * Remote port
-   *
-   * @var resource
-   */
-  protected $context_ = null;
-
-  /**
-   * ServerSocket constructor
-   *
-   * @param string $host        Host to listen on
-   * @param int $port           Port to listen on
-   * @param resource   $context      Stream context
-   * @return void
-   */
-  public function __construct($host = 'localhost', $port = 9090, $context = null)
-  {
-    $ssl_host = $this->getSSLHost($host);
-    parent::__construct($ssl_host, $port);
-    $this->context_ = $context;
-  }
-
-  public function getSSLHost($host)
-  {
-    $transport_protocol_loc = strpos($host, "://");
-    if ($transport_protocol_loc === false) {
-      $host = 'ssl://'.$host;
-    }
-    return $host;
-  }
-
-  /**
-   * Opens a new socket server handle
-   *
-   * @return void
-   */
-  public function listen()
-  {
-    $this->listener_ = @stream_socket_server(
-      $this->host_ . ':' . $this->port_,
-      $errno,
-      $errstr,
-      STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
-      $this->context_);
-  }
-
-  /**
-   * Implementation of accept. If not client is accepted in the given time
-   *
-   * @return TSocket
-   */
-  protected function acceptImpl()
-  {
-    $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
-    if(!$handle) return null;
-
-    $socket = new TSSLSocket();
-    $socket->setHandle($handle);
-
-    return $socket;
-  }
-}
diff --git a/lib/php/lib/Thrift/Server/TServer.php b/lib/php/lib/Thrift/Server/TServer.php
deleted file mode 100644
index f4d76cc..0000000
--- a/lib/php/lib/Thrift/Server/TServer.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-namespace Thrift\Server;
-
-use Thrift\Factory\TTransportFactory;
-use Thrift\Factory\TProtocolFactory;
-
-/**
- * Generic class for a Thrift server.
- *
- * @package thrift.server
- */
-abstract class TServer
-{
-  /**
-   * Processor to handle new clients
-   *
-   * @var TProcessor
-   */
-  protected $processor_;
-
-  /**
-   * Server transport to be used for listening
-   * and accepting new clients
-   *
-   * @var TServerTransport
-   */
-  protected $transport_;
-
-  /**
-   * Input transport factory
-   *
-   * @var TTransportFactory
-   */
-  protected $inputTransportFactory_;
-
-  /**
-   * Output transport factory
-   *
-   * @var TTransportFactory
-   */
-  protected $outputTransportFactory_;
-
-  /**
-   * Input protocol factory
-   *
-   * @var TProtocolFactory
-   */
-  protected $inputProtocolFactory_;
-
-  /**
-   * Output protocol factory
-   *
-   * @var TProtocolFactory
-   */
-  protected $outputProtocolFactory_;
-
-  /**
-   * Sets up all the factories, etc
-   *
-   * @param object $processor
-   * @param TServerTransport $transport
-   * @param TTransportFactory $inputTransportFactory
-   * @param TTransportFactory $outputTransportFactory
-   * @param TProtocolFactory $inputProtocolFactory
-   * @param TProtocolFactory $outputProtocolFactory
-   * @return void
-   */
-  public function __construct($processor,
-                              TServerTransport $transport,
-                              TTransportFactory $inputTransportFactory,
-                              TTransportFactory $outputTransportFactory,
-                              TProtocolFactory $inputProtocolFactory,
-                              TProtocolFactory $outputProtocolFactory) {
-    $this->processor_ = $processor;
-    $this->transport_ = $transport;
-    $this->inputTransportFactory_ = $inputTransportFactory;
-    $this->outputTransportFactory_ = $outputTransportFactory;
-    $this->inputProtocolFactory_ = $inputProtocolFactory;
-    $this->outputProtocolFactory_ = $outputProtocolFactory;
-  }
-
-  /**
-   * Serves the server. This should never return
-   * unless a problem permits it to do so or it
-   * is interrupted intentionally
-   *
-   * @abstract
-   * @return void
-   */
-  abstract public function serve();
-
-  /**
-   * Stops the server serving
-   *
-   * @abstract
-   * @return void
-   */
-  abstract public function stop();
-}
diff --git a/lib/php/lib/Thrift/Server/TServerSocket.php b/lib/php/lib/Thrift/Server/TServerSocket.php
deleted file mode 100644
index da8e226..0000000
--- a/lib/php/lib/Thrift/Server/TServerSocket.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Server;
-
-use Thrift\Transport\TSocket;
-
-/**
- * Socket implementation of a server agent.
- *
- * @package thrift.transport
- */
-class TServerSocket extends TServerTransport
-{
-  /**
-   * Handle for the listener socket
-   *
-   * @var resource
-   */
-  protected $listener_;
-
-  /**
-   * Port for the listener to listen on
-   *
-   * @var int
-   */
-  protected $port_;
-
-  /**
-   * Timeout when listening for a new client
-   *
-   * @var int
-   */
-  protected $acceptTimeout_ = 30000;
-
-  /**
-   * Host to listen on
-   *
-   * @var string
-   */
-  protected $host_;
-
-  /**
-   * ServerSocket constructor
-   *
-   * @param string $host        Host to listen on
-   * @param int $port           Port to listen on
-   * @return void
-   */
-  public function __construct($host = 'localhost', $port = 9090)
-  {
-    $this->host_ = $host;
-    $this->port_ = $port;
-  }
-
-  /**
-   * Sets the accept timeout
-   *
-   * @param int $acceptTimeout
-   * @return void
-   */
-  public function setAcceptTimeout($acceptTimeout)
-  {
-    $this->acceptTimeout_ = $acceptTimeout;
-  }
-
-  /**
-   * Opens a new socket server handle
-   *
-   * @return void
-   */
-  public function listen()
-  {
-    $this->listener_ = stream_socket_server('tcp://' . $this->host_ . ':' . $this->port_);
-  }
-
-  /**
-   * Closes the socket server handle
-   *
-   * @return void
-   */
-  public function close()
-  {
-    @fclose($this->listener_);
-    $this->listener_ = null;
-  }
-
-  /**
-   * Implementation of accept. If not client is accepted in the given time
-   *
-   * @return TSocket
-   */
-  protected function acceptImpl()
-  {
-    $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
-    if(!$handle) return null;
-
-    $socket = new TSocket();
-    $socket->setHandle($handle);
-
-    return $socket;
-  }
-}
diff --git a/lib/php/lib/Thrift/Server/TServerTransport.php b/lib/php/lib/Thrift/Server/TServerTransport.php
deleted file mode 100644
index f82d06d..0000000
--- a/lib/php/lib/Thrift/Server/TServerTransport.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-namespace Thrift\Server;
-
-use Thrift\Exception\TTransportException;
-
-/**
- * Generic class for Server agent.
- *
- * @package thrift.transport
- */
-abstract class TServerTransport
-{
-  /**
-   * List for new clients
-   *
-   * @abstract
-   * @return void
-   */
-  abstract public function listen();
-
-  /**
-   * Close the server
-   *
-   * @abstract
-   * @return void
-   */
-  abstract public function close();
-
-  /**
-   * Subclasses should use this to implement
-   * accept.
-   *
-   * @abstract
-   * @return TTransport
-   */
-  abstract protected function acceptImpl();
-
-  /**
-   * Uses the accept implemtation. If null is returned, an
-   * exception is thrown.
-   *
-   * @throws TTransportException
-   * @return TTransport
-   */
-  public function accept()
-  {
-    $transport = $this->acceptImpl();
-
-    if ($transport == null) {
-      throw new TTransportException("accept() may not return NULL");
-    }
-
-    return $transport;
-  }
-}
diff --git a/lib/php/lib/Thrift/Server/TSimpleServer.php b/lib/php/lib/Thrift/Server/TSimpleServer.php
deleted file mode 100644
index e277700..0000000
--- a/lib/php/lib/Thrift/Server/TSimpleServer.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Thrift\Server;
-
-use Thrift\Exception\TTransportException;
-
-/**
- * Simple implemtation of a Thrift server.
- *
- * @package thrift.server
- */
-class TSimpleServer extends TServer
-{
-  /**
-   * Flag for the main serving loop
-   *
-   * @var bool
-   */
-  private $stop_ = false;
-
-  /**
-   * Listens for new client using the supplied
-   * transport. It handles TTransportExceptions
-   * to avoid timeouts etc killing it
-   *
-   * @return void
-   */
-  public function serve()
-  {
-    $this->transport_->listen();
-
-    while (!$this->stop_) {
-      try {
-        $transport = $this->transport_->accept();
-
-        if ($transport != null) {
-          $inputTransport = $this->inputTransportFactory_->getTransport($transport);
-          $outputTransport = $this->outputTransportFactory_->getTransport($transport);
-          $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
-          $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
-          while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
-        }
-      } catch (TTransportException $e) { }
-    }
-  }
-
-  /**
-   * Stops the server running. Kills the transport
-   * and then stops the main serving loop
-   *
-   * @return void
-   */
-  public function stop()
-  {
-    $this->transport_->close();
-    $this->stop_ = true;
-  }
-}
diff --git a/lib/php/lib/Thrift/Transport/TBufferedTransport.php b/lib/php/lib/Thrift/Transport/TBufferedTransport.php
deleted file mode 100644
index f654ad3..0000000
--- a/lib/php/lib/Thrift/Transport/TBufferedTransport.php
+++ /dev/null
@@ -1,181 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Buffered transport. Stores data to an internal buffer that it doesn't
- * actually write out until flush is called. For reading, we do a greedy
- * read and then serve data out of the internal buffer.
- *
- * @package thrift.transport
- */
-class TBufferedTransport extends TTransport
-{
-  /**
-   * Constructor. Creates a buffered transport around an underlying transport
-   */
-  public function __construct($transport=null, $rBufSize=512, $wBufSize=512)
-  {
-    $this->transport_ = $transport;
-    $this->rBufSize_ = $rBufSize;
-    $this->wBufSize_ = $wBufSize;
-  }
-
-  /**
-   * The underlying transport
-   *
-   * @var TTransport
-   */
-  protected $transport_ = null;
-
-  /**
-   * The receive buffer size
-   *
-   * @var int
-   */
-  protected $rBufSize_ = 512;
-
-  /**
-   * The write buffer size
-   *
-   * @var int
-   */
-  protected $wBufSize_ = 512;
-
-  /**
-   * The write buffer.
-   *
-   * @var string
-   */
-  protected $wBuf_ = '';
-
-  /**
-   * The read buffer.
-   *
-   * @var string
-   */
-  protected $rBuf_ = '';
-
-  public function isOpen()
-  {
-    return $this->transport_->isOpen();
-  }
-
-  public function open()
-  {
-    $this->transport_->open();
-  }
-
-  public function close()
-  {
-    $this->transport_->close();
-  }
-
-  public function putBack($data)
-  {
-    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
-      $this->rBuf_ = $data;
-    } else {
-      $this->rBuf_ = ($data . $this->rBuf_);
-    }
-  }
-
-  /**
-   * The reason that we customize readAll here is that the majority of PHP
-   * streams are already internally buffered by PHP. The socket stream, for
-   * example, buffers internally and blocks if you call read with $len greater
-   * than the amount of data available, unlike recv() in C.
-   *
-   * Therefore, use the readAll method of the wrapped transport inside
-   * the buffered readAll.
-   */
-  public function readAll($len)
-  {
-    $have = TStringFuncFactory::create()->strlen($this->rBuf_);
-    if ($have == 0) {
-      $data = $this->transport_->readAll($len);
-    } elseif ($have < $len) {
-      $data = $this->rBuf_;
-      $this->rBuf_ = '';
-      $data .= $this->transport_->readAll($len - $have);
-    } elseif ($have == $len) {
-      $data = $this->rBuf_;
-      $this->rBuf_ = '';
-    } elseif ($have > $len) {
-      $data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
-      $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
-    }
-
-    return $data;
-  }
-
-  public function read($len)
-  {
-    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
-      $this->rBuf_ = $this->transport_->read($this->rBufSize_);
-    }
-
-    if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) {
-      $ret = $this->rBuf_;
-      $this->rBuf_ = '';
-
-      return $ret;
-    }
-
-    $ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
-    $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
-
-    return $ret;
-  }
-
-  public function write($buf)
-  {
-    $this->wBuf_ .= $buf;
-    if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) {
-      $out = $this->wBuf_;
-
-      // Note that we clear the internal wBuf_ prior to the underlying write
-      // to ensure we're in a sane state (i.e. internal buffer cleaned)
-      // if the underlying write throws up an exception
-      $this->wBuf_ = '';
-      $this->transport_->write($out);
-    }
-  }
-
-  public function flush()
-  {
-    if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) {
-      $out = $this->wBuf_;
-
-      // Note that we clear the internal wBuf_ prior to the underlying write
-      // to ensure we're in a sane state (i.e. internal buffer cleaned)
-      // if the underlying write throws up an exception
-      $this->wBuf_ = '';
-      $this->transport_->write($out);
-    }
-    $this->transport_->flush();
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Transport/TCurlClient.php b/lib/php/lib/Thrift/Transport/TCurlClient.php
deleted file mode 100644
index c761cd0..0000000
--- a/lib/php/lib/Thrift/Transport/TCurlClient.php
+++ /dev/null
@@ -1,249 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TTransportException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * HTTP client for Thrift
- *
- * @package thrift.transport
- */
-class TCurlClient extends TTransport
-{
-  private static $curlHandle;
-
-  /**
-   * The host to connect to
-   *
-   * @var string
-   */
-  protected $host_;
-
-  /**
-   * The port to connect on
-   *
-   * @var int
-   */
-  protected $port_;
-
-  /**
-   * The URI to request
-   *
-   * @var string
-   */
-  protected $uri_;
-
-  /**
-   * The scheme to use for the request, i.e. http, https
-   *
-   * @var string
-   */
-  protected $scheme_;
-
-  /**
-   * Buffer for the HTTP request data
-   *
-   * @var string
-   */
-  protected $request_;
-
-  /**
-   * Buffer for the HTTP response data.
-   *
-   * @var binary string
-   */
-  protected $response_;
-
-  /**
-   * Read timeout
-   *
-   * @var float
-   */
-  protected $timeout_;
-
-  /**
-   * http headers
-   *
-   * @var array
-   */
-  protected $headers_;
-
-  /**
-   * Make a new HTTP client.
-   *
-   * @param string $host
-   * @param int    $port
-   * @param string $uri
-   */
-  public function __construct($host, $port=80, $uri='', $scheme = 'http')
-  {
-    if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
-      $uri = '/'.$uri;
-    }
-    $this->scheme_ = $scheme;
-    $this->host_ = $host;
-    $this->port_ = $port;
-    $this->uri_ = $uri;
-    $this->request_ = '';
-    $this->response_ = null;
-    $this->timeout_ = null;
-    $this->headers_ = array();
-  }
-
-  /**
-   * Set read timeout
-   *
-   * @param float $timeout
-   */
-  public function setTimeoutSecs($timeout)
-  {
-    $this->timeout_ = $timeout;
-  }
-
-  /**
-   * Whether this transport is open.
-   *
-   * @return boolean true if open
-   */
-  public function isOpen()
-  {
-    return true;
-  }
-
-  /**
-   * Open the transport for reading/writing
-   *
-   * @throws TTransportException if cannot open
-   */
-  public function open()
-  {
-  }
-
-  /**
-   * Close the transport.
-   */
-  public function close()
-  {
-    $this->request_ = '';
-    $this->response_ = null;
-  }
-
-  /**
-   * Read some data into the array.
-   *
-   * @param int    $len How much to read
-   * @return string The data that has been read
-   * @throws TTransportException if cannot read any more data
-   */
-  public function read($len)
-  {
-    if ($len >= strlen($this->response_)) {
-      return $this->response_;
-    } else {
-      $ret = substr($this->response_, 0, $len);
-      $this->response_ = substr($this->response_, $len);
-
-      return $ret;
-    }
-  }
-
-  /**
-   * Writes some data into the pending buffer
-   *
-   * @param string $buf  The data to write
-   * @throws TTransportException if writing fails
-   */
-  public function write($buf)
-  {
-    $this->request_ .= $buf;
-  }
-
-  /**
-   * Opens and sends the actual request over the HTTP connection
-   *
-   * @throws TTransportException if a writing error occurs
-   */
-  public function flush()
-  {
-    if (!self::$curlHandle) {
-      register_shutdown_function(array('Thrift\\Transport\\TCurlClient', 'closeCurlHandle'));
-      self::$curlHandle = curl_init();
-      curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true);
-      curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true);
-      curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
-      curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
-      curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true);
-      curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1);
-    }
-    // God, PHP really has some esoteric ways of doing simple things.
-    $host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
-    $fullUrl = $this->scheme_."://".$host.$this->uri_;
-
-    $headers = array();
-    $defaultHeaders = array('Accept' => 'application/x-thrift',
-                     'Content-Type' => 'application/x-thrift',
-                     'Content-Length' => TStringFuncFactory::create()->strlen($this->request_));
-    foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
-      $headers[] = "$key: $value";
-    }
-
-    curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers);
-
-    if ($this->timeout_ > 0) {
-      curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_);
-    }
-    curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_);
-    $this->request_ = '';
-
-    curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl);
-    $this->response_ = curl_exec(self::$curlHandle);
-
-    // Connect failed?
-    if (!$this->response_) {
-      curl_close(self::$curlHandle);
-      self::$curlHandle = null;
-      $error = 'TCurlClient: Could not connect to '.$fullUrl;
-      throw new TTransportException($error, TTransportException::NOT_OPEN);
-    }
-  }
-
-  public static function closeCurlHandle()
-  {
-    try {
-      if (self::$curlHandle) {
-        curl_close(self::$curlHandle);
-        self::$curlHandle = null;
-      }
-    } catch (\Exception $x) {
-      error_log('There was an error closing the curl handle: ' . $x->getMessage());
-    }
-  }
-
-  public function addHeaders($headers)
-  {
-    $this->headers_ = array_merge($this->headers_, $headers);
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Transport/TFramedTransport.php b/lib/php/lib/Thrift/Transport/TFramedTransport.php
deleted file mode 100644
index b8a64a9..0000000
--- a/lib/php/lib/Thrift/Transport/TFramedTransport.php
+++ /dev/null
@@ -1,193 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Framed transport. Writes and reads data in chunks that are stamped with
- * their length.
- *
- * @package thrift.transport
- */
-class TFramedTransport extends TTransport
-{
-  /**
-   * Underlying transport object.
-   *
-   * @var TTransport
-   */
-  private $transport_;
-
-  /**
-   * Buffer for read data.
-   *
-   * @var string
-   */
-  private $rBuf_;
-
-  /**
-   * Buffer for queued output data
-   *
-   * @var string
-   */
-  private $wBuf_;
-
-  /**
-   * Whether to frame reads
-   *
-   * @var bool
-   */
-  private $read_;
-
-  /**
-   * Whether to frame writes
-   *
-   * @var bool
-   */
-  private $write_;
-
-  /**
-   * Constructor.
-   *
-   * @param TTransport $transport Underlying transport
-   */
-  public function __construct($transport=null, $read=true, $write=true)
-  {
-    $this->transport_ = $transport;
-    $this->read_ = $read;
-    $this->write_ = $write;
-  }
-
-  public function isOpen()
-  {
-    return $this->transport_->isOpen();
-  }
-
-  public function open()
-  {
-    $this->transport_->open();
-  }
-
-  public function close()
-  {
-    $this->transport_->close();
-  }
-
-  /**
-   * Reads from the buffer. When more data is required reads another entire
-   * chunk and serves future reads out of that.
-   *
-   * @param int $len How much data
-   */
-  public function read($len)
-  {
-    if (!$this->read_) {
-      return $this->transport_->read($len);
-    }
-
-    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
-      $this->readFrame();
-    }
-
-    // Just return full buff
-    if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) {
-      $out = $this->rBuf_;
-      $this->rBuf_ = null;
-
-      return $out;
-    }
-
-    // Return TStringFuncFactory::create()->substr
-    $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
-    $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
-
-    return $out;
-  }
-
-  /**
-   * Put previously read data back into the buffer
-   *
-   * @param string $data data to return
-   */
-  public function putBack($data)
-  {
-    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
-      $this->rBuf_ = $data;
-    } else {
-      $this->rBuf_ = ($data . $this->rBuf_);
-    }
-  }
-
-  /**
-   * Reads a chunk of data into the internal read buffer.
-   */
-  private function readFrame()
-  {
-    $buf = $this->transport_->readAll(4);
-    $val = unpack('N', $buf);
-    $sz = $val[1];
-
-    $this->rBuf_ = $this->transport_->readAll($sz);
-  }
-
-  /**
-   * Writes some data to the pending output buffer.
-   *
-   * @param string $buf The data
-   * @param int    $len Limit of bytes to write
-   */
-  public function write($buf, $len=null)
-  {
-    if (!$this->write_) {
-      return $this->transport_->write($buf, $len);
-    }
-
-    if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) {
-      $buf = TStringFuncFactory::create()->substr($buf, 0, $len);
-    }
-    $this->wBuf_ .= $buf;
-  }
-
-  /**
-   * Writes the output buffer to the stream in the format of a 4-byte length
-   * followed by the actual data.
-   */
-  public function flush()
-  {
-    if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) {
-      return $this->transport_->flush();
-    }
-
-    $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_));
-    $out .= $this->wBuf_;
-
-    // Note that we clear the internal wBuf_ prior to the underlying write
-    // to ensure we're in a sane state (i.e. internal buffer cleaned)
-    // if the underlying write throws up an exception
-    $this->wBuf_ = '';
-    $this->transport_->write($out);
-    $this->transport_->flush();
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Transport/THttpClient.php b/lib/php/lib/Thrift/Transport/THttpClient.php
deleted file mode 100644
index b372ab7..0000000
--- a/lib/php/lib/Thrift/Transport/THttpClient.php
+++ /dev/null
@@ -1,229 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TTransportException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * HTTP client for Thrift
- *
- * @package thrift.transport
- */
-class THttpClient extends TTransport
-{
-  /**
-   * The host to connect to
-   *
-   * @var string
-   */
-  protected $host_;
-
-  /**
-   * The port to connect on
-   *
-   * @var int
-   */
-  protected $port_;
-
-  /**
-   * The URI to request
-   *
-   * @var string
-   */
-  protected $uri_;
-
-  /**
-   * The scheme to use for the request, i.e. http, https
-   *
-   * @var string
-   */
-  protected $scheme_;
-
-  /**
-   * Buffer for the HTTP request data
-   *
-   * @var string
-   */
-  protected $buf_;
-
-  /**
-   * Input socket stream.
-   *
-   * @var resource
-   */
-  protected $handle_;
-
-  /**
-   * Read timeout
-   *
-   * @var float
-   */
-  protected $timeout_;
-
-  /**
-   * http headers
-   *
-   * @var array
-   */
-  protected $headers_;
-
-  /**
-   * Make a new HTTP client.
-   *
-   * @param string $host
-   * @param int    $port
-   * @param string $uri
-   */
-  public function __construct($host, $port=80, $uri='', $scheme = 'http')
-  {
-    if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
-      $uri = '/'.$uri;
-    }
-    $this->scheme_ = $scheme;
-    $this->host_ = $host;
-    $this->port_ = $port;
-    $this->uri_ = $uri;
-    $this->buf_ = '';
-    $this->handle_ = null;
-    $this->timeout_ = null;
-    $this->headers_ = array();
-  }
-
-  /**
-   * Set read timeout
-   *
-   * @param float $timeout
-   */
-  public function setTimeoutSecs($timeout)
-  {
-    $this->timeout_ = $timeout;
-  }
-
-  /**
-   * Whether this transport is open.
-   *
-   * @return boolean true if open
-   */
-  public function isOpen()
-  {
-    return true;
-  }
-
-  /**
-   * Open the transport for reading/writing
-   *
-   * @throws TTransportException if cannot open
-   */
-  public function open() {}
-
-  /**
-   * Close the transport.
-   */
-  public function close()
-  {
-    if ($this->handle_) {
-      @fclose($this->handle_);
-      $this->handle_ = null;
-    }
-  }
-
-  /**
-   * Read some data into the array.
-   *
-   * @param int    $len How much to read
-   * @return string The data that has been read
-   * @throws TTransportException if cannot read any more data
-   */
-  public function read($len)
-  {
-    $data = @fread($this->handle_, $len);
-    if ($data === FALSE || $data === '') {
-      $md = stream_get_meta_data($this->handle_);
-      if ($md['timed_out']) {
-        throw new TTransportException('THttpClient: timed out reading '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::TIMED_OUT);
-      } else {
-        throw new TTransportException('THttpClient: Could not read '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::UNKNOWN);
-      }
-    }
-
-    return $data;
-  }
-
-  /**
-   * Writes some data into the pending buffer
-   *
-   * @param string $buf  The data to write
-   * @throws TTransportException if writing fails
-   */
-  public function write($buf)
-  {
-    $this->buf_ .= $buf;
-  }
-
-  /**
-   * Opens and sends the actual request over the HTTP connection
-   *
-   * @throws TTransportException if a writing error occurs
-   */
-  public function flush()
-  {
-    // God, PHP really has some esoteric ways of doing simple things.
-    $host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
-
-    $headers = array();
-    $defaultHeaders = array('Host' => $host,
-                            'Accept' => 'application/x-thrift',
-                            'User-Agent' => 'PHP/THttpClient',
-                            'Content-Type' => 'application/x-thrift',
-                            'Content-Length' => TStringFuncFactory::create()->strlen($this->buf_));
-    foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
-        $headers[] = "$key: $value";
-    }
-
-    $options = array('method' => 'POST',
-                     'header' => implode("\r\n", $headers),
-                     'max_redirects' => 1,
-                     'content' => $this->buf_);
-    if ($this->timeout_ > 0) {
-      $options['timeout'] = $this->timeout_;
-    }
-    $this->buf_ = '';
-
-    $contextid = stream_context_create(array('http' => $options));
-    $this->handle_ = @fopen($this->scheme_.'://'.$host.$this->uri_, 'r', false, $contextid);
-
-    // Connect failed?
-    if ($this->handle_ === FALSE) {
-      $this->handle_ = null;
-      $error = 'THttpClient: Could not connect to '.$host.$this->uri_;
-      throw new TTransportException($error, TTransportException::NOT_OPEN);
-    }
-  }
-
-  public function addHeaders($headers)
-  {
-    $this->headers_ = array_merge($this->headers_, $headers);
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Transport/TMemoryBuffer.php b/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
deleted file mode 100644
index ca31c57..0000000
--- a/lib/php/lib/Thrift/Transport/TMemoryBuffer.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TTransportException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * A memory buffer is a tranpsort that simply reads from and writes to an
- * in-memory string buffer. Anytime you call write on it, the data is simply
- * placed into a buffer, and anytime you call read, data is read from that
- * buffer.
- *
- * @package thrift.transport
- */
-class TMemoryBuffer extends TTransport
-{
-  /**
-   * Constructor. Optionally pass an initial value
-   * for the buffer.
-   */
-  public function __construct($buf = '')
-  {
-    $this->buf_ = $buf;
-  }
-
-  protected $buf_ = '';
-
-  public function isOpen()
-  {
-    return true;
-  }
-
-  public function open() {}
-
-  public function close() {}
-
-  public function write($buf)
-  {
-    $this->buf_ .= $buf;
-  }
-
-  public function read($len)
-  {
-    $bufLength = TStringFuncFactory::create()->strlen($this->buf_);
-
-    if ($bufLength === 0) {
-      throw new TTransportException('TMemoryBuffer: Could not read ' .
-                                    $len . ' bytes from buffer.',
-                                    TTransportException::UNKNOWN);
-    }
-
-    if ($bufLength <= $len) {
-      $ret = $this->buf_;
-      $this->buf_ = '';
-
-      return $ret;
-    }
-
-    $ret = TStringFuncFactory::create()->substr($this->buf_, 0, $len);
-    $this->buf_ = TStringFuncFactory::create()->substr($this->buf_, $len);
-
-    return $ret;
-  }
-
-  public function getBuffer()
-  {
-    return $this->buf_;
-  }
-
-  public function available()
-  {
-    return TStringFuncFactory::create()->strlen($this->buf_);
-  }
-
-  public function putBack($data)
-  {
-    $this->buf_ = $data.$this->buf_;
-  }
-}
diff --git a/lib/php/lib/Thrift/Transport/TPhpStream.php b/lib/php/lib/Thrift/Transport/TPhpStream.php
deleted file mode 100644
index 4c14cdf..0000000
--- a/lib/php/lib/Thrift/Transport/TPhpStream.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Php stream transport. Reads to and writes from the php standard streams
- * php://input and php://output
- *
- * @package thrift.transport
- */
-class TPhpStream extends TTransport
-{
-  const MODE_R = 1;
-  const MODE_W = 2;
-
-  private $inStream_ = null;
-
-  private $outStream_ = null;
-
-  private $read_ = false;
-
-  private $write_ = false;
-
-  public function __construct($mode)
-  {
-    $this->read_ = $mode & self::MODE_R;
-    $this->write_ = $mode & self::MODE_W;
-  }
-
-  public function open()
-  {
-    if ($this->read_) {
-      $this->inStream_ = @fopen(self::inStreamName(), 'r');
-      if (!is_resource($this->inStream_)) {
-        throw new TException('TPhpStream: Could not open php://input');
-      }
-    }
-    if ($this->write_) {
-      $this->outStream_ = @fopen('php://output', 'w');
-      if (!is_resource($this->outStream_)) {
-        throw new TException('TPhpStream: Could not open php://output');
-      }
-    }
-  }
-
-  public function close()
-  {
-    if ($this->read_) {
-      @fclose($this->inStream_);
-      $this->inStream_ = null;
-    }
-    if ($this->write_) {
-      @fclose($this->outStream_);
-      $this->outStream_ = null;
-    }
-  }
-
-  public function isOpen()
-  {
-    return
-      (!$this->read_ || is_resource($this->inStream_)) &&
-      (!$this->write_ || is_resource($this->outStream_));
-  }
-
-  public function read($len)
-  {
-    $data = @fread($this->inStream_, $len);
-    if ($data === FALSE || $data === '') {
-      throw new TException('TPhpStream: Could not read '.$len.' bytes');
-    }
-
-    return $data;
-  }
-
-  public function write($buf)
-  {
-    while (TStringFuncFactory::create()->strlen($buf) > 0) {
-      $got = @fwrite($this->outStream_, $buf);
-      if ($got === 0 || $got === FALSE) {
-        throw new TException('TPhpStream: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes');
-      }
-      $buf = TStringFuncFactory::create()->substr($buf, $got);
-    }
-  }
-
-  public function flush()
-  {
-    @fflush($this->outStream_);
-  }
-
-  private static function inStreamName()
-  {
-    if (php_sapi_name() == 'cli') {
-      return 'php://stdin';
-    }
-
-    return 'php://input';
-  }
-
-}
diff --git a/lib/php/lib/Thrift/Transport/TSSLSocket.php b/lib/php/lib/Thrift/Transport/TSSLSocket.php
deleted file mode 100644
index 533b7bb..0000000
--- a/lib/php/lib/Thrift/Transport/TSSLSocket.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TException;
-use Thrift\Exception\TTransportException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Sockets implementation of the TTransport interface.
- *
- * @package thrift.transport
- */
-class TSSLSocket extends TSocket
-{
-  /**
-   * Remote port
-   *
-   * @var resource
-   */
-  protected $context_ = null;
-
-  /**
-   * Socket constructor
-   *
-   * @param string     $host         Remote hostname
-   * @param int        $port         Remote port
-   * @param resource   $context      Stream context
-   * @param bool       $persist      Whether to use a persistent socket
-   * @param string     $debugHandler Function to call for error logging
-   */
-  public function __construct($host='localhost',
-                              $port=9090,
-                              $context=null,
-                              $debugHandler=null) {
-    $this->host_ = $this->getSSLHost($host);
-    $this->port_ = $port;
-    $this->context_ = $context;
-    $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
-  }
-
-  /**
-   * Creates a host name with SSL transport protocol
-   * if no transport protocol already specified in
-   * the host name.
-   *
-   * @param string $host    Host to listen on
-   * @return string $host   Host name with transport protocol
-   */
-  private function getSSLHost($host)
-  {
-    $transport_protocol_loc = strpos($host, "://");
-    if ($transport_protocol_loc === false) {
-      $host = 'ssl://'.$host;
-    }
-    return $host;
-  }
-
-  /**
-   * Connects the socket.
-   */
-  public function open()
-  {
-    if ($this->isOpen()) {
-      throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
-    }
-
-    if (empty($this->host_)) {
-      throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
-    }
-
-    if ($this->port_ <= 0) {
-      throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
-    }
-
-    $this->handle_ = @stream_socket_client($this->host_.':'.$this->port_,
-                                          $errno,
-                                          $errstr,
-                                          $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000),
-                                          STREAM_CLIENT_CONNECT,
-                                          $this->context_);
-
-    // Connect failed?
-    if ($this->handle_ === FALSE) {
-      $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
-      if ($this->debug_) {
-        call_user_func($this->debugHandler_, $error);
-      }
-      throw new TException($error);
-    }
-  }
-}
diff --git a/lib/php/lib/Thrift/Transport/TSocket.php b/lib/php/lib/Thrift/Transport/TSocket.php
deleted file mode 100644
index a1872b9..0000000
--- a/lib/php/lib/Thrift/Transport/TSocket.php
+++ /dev/null
@@ -1,340 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TException;
-use Thrift\Exception\TTransportException;
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Sockets implementation of the TTransport interface.
- *
- * @package thrift.transport
- */
-class TSocket extends TTransport
-{
-  /**
-   * Handle to PHP socket
-   *
-   * @var resource
-   */
-  protected $handle_ = null;
-
-  /**
-   * Remote hostname
-   *
-   * @var string
-   */
-  protected $host_ = 'localhost';
-
-  /**
-   * Remote port
-   *
-   * @var int
-   */
-  protected $port_ = '9090';
-
-  /**
-   * Send timeout in seconds.
-   *
-   * Combined with sendTimeoutUsec this is used for send timeouts.
-   *
-   * @var int
-   */
-  protected $sendTimeoutSec_ = 0;
-
-  /**
-   * Send timeout in microseconds.
-   *
-   * Combined with sendTimeoutSec this is used for send timeouts.
-   *
-   * @var int
-   */
-  protected $sendTimeoutUsec_ = 100000;
-
-  /**
-   * Recv timeout in seconds
-   *
-   * Combined with recvTimeoutUsec this is used for recv timeouts.
-   *
-   * @var int
-   */
-  protected $recvTimeoutSec_ = 0;
-
-  /**
-   * Recv timeout in microseconds
-   *
-   * Combined with recvTimeoutSec this is used for recv timeouts.
-   *
-   * @var int
-   */
-  protected $recvTimeoutUsec_ = 750000;
-
-  /**
-   * Persistent socket or plain?
-   *
-   * @var bool
-   */
-  protected $persist_ = false;
-
-  /**
-   * Debugging on?
-   *
-   * @var bool
-   */
-  protected $debug_ = false;
-
-  /**
-   * Debug handler
-   *
-   * @var mixed
-   */
-  protected $debugHandler_ = null;
-
-  /**
-   * Socket constructor
-   *
-   * @param string $host         Remote hostname
-   * @param int    $port         Remote port
-   * @param bool   $persist      Whether to use a persistent socket
-   * @param string $debugHandler Function to call for error logging
-   */
-  public function __construct($host='localhost',
-                              $port=9090,
-                              $persist=false,
-                              $debugHandler=null) {
-    $this->host_ = $host;
-    $this->port_ = $port;
-    $this->persist_ = $persist;
-    $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
-  }
-
-  /**
-   * @param resource $handle
-   * @return void
-   */
-  public function setHandle($handle)
-  {
-    $this->handle_ = $handle;
-  }
-
-  /**
-   * Sets the send timeout.
-   *
-   * @param int $timeout  Timeout in milliseconds.
-   */
-  public function setSendTimeout($timeout)
-  {
-    $this->sendTimeoutSec_ = floor($timeout / 1000);
-    $this->sendTimeoutUsec_ =
-            ($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000;
-  }
-
-  /**
-   * Sets the receive timeout.
-   *
-   * @param int $timeout  Timeout in milliseconds.
-   */
-  public function setRecvTimeout($timeout)
-  {
-    $this->recvTimeoutSec_ = floor($timeout / 1000);
-    $this->recvTimeoutUsec_ =
-            ($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000;
-  }
-
-  /**
-   * Sets debugging output on or off
-   *
-   * @param bool $debug
-   */
-  public function setDebug($debug)
-  {
-    $this->debug_ = $debug;
-  }
-
-  /**
-   * Get the host that this socket is connected to
-   *
-   * @return string host
-   */
-  public function getHost()
-  {
-    return $this->host_;
-  }
-
-  /**
-   * Get the remote port that this socket is connected to
-   *
-   * @return int port
-   */
-  public function getPort()
-  {
-    return $this->port_;
-  }
-
-  /**
-   * Tests whether this is open
-   *
-   * @return bool true if the socket is open
-   */
-  public function isOpen()
-  {
-    return is_resource($this->handle_);
-  }
-
-  /**
-   * Connects the socket.
-   */
-  public function open()
-  {
-    if ($this->isOpen()) {
-      throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
-    }
-
-    if (empty($this->host_)) {
-      throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
-    }
-
-    if ($this->port_ <= 0) {
-      throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
-    }
-
-    if ($this->persist_) {
-      $this->handle_ = @pfsockopen($this->host_,
-                                   $this->port_,
-                                   $errno,
-                                   $errstr,
-                                   $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
-    } else {
-      $this->handle_ = @fsockopen($this->host_,
-                                  $this->port_,
-                                  $errno,
-                                  $errstr,
-                                  $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
-    }
-
-    // Connect failed?
-    if ($this->handle_ === FALSE) {
-      $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
-      if ($this->debug_) {
-        call_user_func($this->debugHandler_, $error);
-      }
-      throw new TException($error);
-    }
-
-    if (function_exists('socket_import_stream') && function_exists('socket_set_option')) {
-      $socket = socket_import_stream($this->handle_);
-      socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);
-    }
-  }
-
-  /**
-   * Closes the socket.
-   */
-  public function close()
-  {
-    @fclose($this->handle_);
-    $this->handle_ = null;
-  }
-
-  /**
-   * Read from the socket at most $len bytes.
-   *
-   * This method will not wait for all the requested data, it will return as
-   * soon as any data is received.
-   *
-   * @param int $len Maximum number of bytes to read.
-   * @return string Binary data
-   */
-  public function read($len)
-  {
-    $null = null;
-    $read = array($this->handle_);
-    $readable = @stream_select($read, $null, $null, $this->recvTimeoutSec_, $this->recvTimeoutUsec_);
-
-    if ($readable > 0) {
-      $data = fread($this->handle_, $len);
-      if ($data === false) {
-          throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
-                               $this->host_.':'.$this->port_);
-      } elseif ($data == '' && feof($this->handle_)) {
-          throw new TTransportException('TSocket read 0 bytes');
-        }
-
-      return $data;
-    } elseif ($readable === 0) {
-        throw new TTransportException('TSocket: timed out reading '.$len.' bytes from '.
-                             $this->host_.':'.$this->port_);
-      } else {
-        throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
-                             $this->host_.':'.$this->port_);
-      }
-    }
-
-  /**
-   * Write to the socket.
-   *
-   * @param string $buf The data to write
-   */
-  public function write($buf)
-  {
-    $null = null;
-    $write = array($this->handle_);
-
-    // keep writing until all the data has been written
-    while (TStringFuncFactory::create()->strlen($buf) > 0) {
-      // wait for stream to become available for writing
-      $writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
-      if ($writable > 0) {
-        // write buffer to stream
-        $written = fwrite($this->handle_, $buf);
-        if ($written === -1 || $written === false) {
-          throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
-                                   $this->host_.':'.$this->port_);
-        }
-        // determine how much of the buffer is left to write
-        $buf = TStringFuncFactory::create()->substr($buf, $written);
-      } elseif ($writable === 0) {
-          throw new TTransportException('TSocket: timed out writing '.TStringFuncFactory::create()->strlen($buf).' bytes from '.
-                               $this->host_.':'.$this->port_);
-        } else {
-            throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
-                                 $this->host_.':'.$this->port_);
-        }
-      }
-    }
-
-  /**
-   * Flush output to the socket.
-   *
-   * Since read(), readAll() and write() operate on the sockets directly,
-   * this is a no-op
-   *
-   * If you wish to have flushable buffering behaviour, wrap this TSocket
-   * in a TBufferedTransport.
-   */
-  public function flush()
-  {
-    // no-op
-    }
-  }
diff --git a/lib/php/lib/Thrift/Transport/TSocketPool.php b/lib/php/lib/Thrift/Transport/TSocketPool.php
deleted file mode 100644
index 18ffd8d..0000000
--- a/lib/php/lib/Thrift/Transport/TSocketPool.php
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Exception\TException;
-
-/**
- * This library makes use of APC cache to make hosts as down in a web
- * environment. If you are running from the CLI or on a system without APC
- * installed, then these null functions will step in and act like cache
- * misses.
- */
-if (!function_exists('apc_fetch')) {
-  function apc_fetch($key) { return FALSE; }
-  function apc_store($key, $var, $ttl=0) { return FALSE; }
-}
-
-/**
- * Sockets implementation of the TTransport interface that allows connection
- * to a pool of servers.
- *
- * @package thrift.transport
- */
-class TSocketPool extends TSocket
-{
-  /**
-   * Remote servers. Array of associative arrays with 'host' and 'port' keys
-   */
-  private $servers_ = array();
-
-  /**
-   * How many times to retry each host in connect
-   *
-   * @var int
-   */
-  private $numRetries_ = 1;
-
-  /**
-   * Retry interval in seconds, how long to not try a host if it has been
-   * marked as down.
-   *
-   * @var int
-   */
-  private $retryInterval_ = 60;
-
-  /**
-   * Max consecutive failures before marking a host down.
-   *
-   * @var int
-   */
-  private $maxConsecutiveFailures_ = 1;
-
-  /**
-   * Try hosts in order? or Randomized?
-   *
-   * @var bool
-   */
-  private $randomize_ = true;
-
-  /**
-   * Always try last host, even if marked down?
-   *
-   * @var bool
-   */
-  private $alwaysTryLast_ = true;
-
-  /**
-   * Socket pool constructor
-   *
-   * @param array  $hosts        List of remote hostnames
-   * @param mixed  $ports        Array of remote ports, or a single common port
-   * @param bool   $persist      Whether to use a persistent socket
-   * @param mixed  $debugHandler Function for error logging
-   */
-  public function __construct($hosts=array('localhost'),
-                              $ports=array(9090),
-                              $persist=false,
-                              $debugHandler=null) {
-    parent::__construct(null, 0, $persist, $debugHandler);
-
-    if (!is_array($ports)) {
-      $port = $ports;
-      $ports = array();
-      foreach ($hosts as $key => $val) {
-        $ports[$key] = $port;
-      }
-    }
-
-    foreach ($hosts as $key => $host) {
-      $this->servers_ []= array('host' => $host,
-                                'port' => $ports[$key]);
-    }
-  }
-
-  /**
-   * Add a server to the pool
-   *
-   * This function does not prevent you from adding a duplicate server entry.
-   *
-   * @param string $host hostname or IP
-   * @param int $port port
-   */
-  public function addServer($host, $port)
-  {
-    $this->servers_[] = array('host' => $host, 'port' => $port);
-  }
-
-  /**
-   * Sets how many time to keep retrying a host in the connect function.
-   *
-   * @param int $numRetries
-   */
-  public function setNumRetries($numRetries)
-  {
-    $this->numRetries_ = $numRetries;
-  }
-
-  /**
-   * Sets how long to wait until retrying a host if it was marked down
-   *
-   * @param int $numRetries
-   */
-  public function setRetryInterval($retryInterval)
-  {
-    $this->retryInterval_ = $retryInterval;
-  }
-
-  /**
-   * Sets how many time to keep retrying a host before marking it as down.
-   *
-   * @param int $numRetries
-   */
-  public function setMaxConsecutiveFailures($maxConsecutiveFailures)
-  {
-    $this->maxConsecutiveFailures_ = $maxConsecutiveFailures;
-  }
-
-  /**
-   * Turns randomization in connect order on or off.
-   *
-   * @param bool $randomize
-   */
-  public function setRandomize($randomize)
-  {
-    $this->randomize_ = $randomize;
-  }
-
-  /**
-   * Whether to always try the last server.
-   *
-   * @param bool $alwaysTryLast
-   */
-  public function setAlwaysTryLast($alwaysTryLast)
-  {
-    $this->alwaysTryLast_ = $alwaysTryLast;
-  }
-
-  /**
-   * Connects the socket by iterating through all the servers in the pool
-   * and trying to find one that works.
-   */
-  public function open()
-  {
-    // Check if we want order randomization
-    if ($this->randomize_) {
-      shuffle($this->servers_);
-    }
-
-    // Count servers to identify the "last" one
-    $numServers = count($this->servers_);
-
-    for ($i = 0; $i < $numServers; ++$i) {
-
-      // This extracts the $host and $port variables
-      extract($this->servers_[$i]);
-
-      // Check APC cache for a record of this server being down
-      $failtimeKey = 'thrift_failtime:'.$host.':'.$port.'~';
-
-      // Cache miss? Assume it's OK
-      $lastFailtime = apc_fetch($failtimeKey);
-      if ($lastFailtime === FALSE) {
-        $lastFailtime = 0;
-      }
-
-      $retryIntervalPassed = false;
-
-      // Cache hit...make sure enough the retry interval has elapsed
-      if ($lastFailtime > 0) {
-        $elapsed = time() - $lastFailtime;
-        if ($elapsed > $this->retryInterval_) {
-          $retryIntervalPassed = true;
-          if ($this->debug_) {
-            call_user_func($this->debugHandler_,
-                           'TSocketPool: retryInterval '.
-                           '('.$this->retryInterval_.') '.
-                           'has passed for host '.$host.':'.$port);
-          }
-        }
-      }
-
-      // Only connect if not in the middle of a fail interval, OR if this
-      // is the LAST server we are trying, just hammer away on it
-      $isLastServer = false;
-      if ($this->alwaysTryLast_) {
-        $isLastServer = ($i == ($numServers - 1));
-      }
-
-      if (($lastFailtime === 0) ||
-          ($isLastServer) ||
-          ($lastFailtime > 0 && $retryIntervalPassed)) {
-
-        // Set underlying TSocket params to this one
-        $this->host_ = $host;
-        $this->port_ = $port;
-
-        // Try up to numRetries_ connections per server
-        for ($attempt = 0; $attempt < $this->numRetries_; $attempt++) {
-          try {
-            // Use the underlying TSocket open function
-            parent::open();
-
-            // Only clear the failure counts if required to do so
-            if ($lastFailtime > 0) {
-              apc_store($failtimeKey, 0);
-            }
-
-            // Successful connection, return now
-            return;
-
-          } catch (TException $tx) {
-            // Connection failed
-          }
-        }
-
-        // Mark failure of this host in the cache
-        $consecfailsKey = 'thrift_consecfails:'.$host.':'.$port.'~';
-
-        // Ignore cache misses
-        $consecfails = apc_fetch($consecfailsKey);
-        if ($consecfails === FALSE) {
-          $consecfails = 0;
-        }
-
-        // Increment by one
-        $consecfails++;
-
-        // Log and cache this failure
-        if ($consecfails >= $this->maxConsecutiveFailures_) {
-          if ($this->debug_) {
-            call_user_func($this->debugHandler_,
-                           'TSocketPool: marking '.$host.':'.$port.
-                           ' as down for '.$this->retryInterval_.' secs '.
-                           'after '.$consecfails.' failed attempts.');
-          }
-          // Store the failure time
-          apc_store($failtimeKey, time());
-
-          // Clear the count of consecutive failures
-          apc_store($consecfailsKey, 0);
-        } else {
-          apc_store($consecfailsKey, $consecfails);
-        }
-      }
-    }
-
-    // Oh no; we failed them all. The system is totally ill!
-    $error = 'TSocketPool: All hosts in pool are down. ';
-    $hosts = array();
-    foreach ($this->servers_ as $server) {
-      $hosts []= $server['host'].':'.$server['port'];
-    }
-    $hostlist = implode(',', $hosts);
-    $error .= '('.$hostlist.')';
-    if ($this->debug_) {
-      call_user_func($this->debugHandler_, $error);
-    }
-    throw new TException($error);
-  }
-}
diff --git a/lib/php/lib/Thrift/Transport/TTransport.php b/lib/php/lib/Thrift/Transport/TTransport.php
deleted file mode 100644
index 99c39ff..0000000
--- a/lib/php/lib/Thrift/Transport/TTransport.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/*
- * 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.
- *
- * @package thrift.transport
- */
-
-namespace Thrift\Transport;
-
-use Thrift\Factory\TStringFuncFactory;
-
-/**
- * Base interface for a transport agent.
- *
- * @package thrift.transport
- */
-abstract class TTransport
-{
-  /**
-   * Whether this transport is open.
-   *
-   * @return boolean true if open
-   */
-  abstract public function isOpen();
-
-  /**
-   * Open the transport for reading/writing
-   *
-   * @throws TTransportException if cannot open
-   */
-  abstract public function open();
-
-  /**
-   * Close the transport.
-   */
-  abstract public function close();
-
-  /**
-   * Read some data into the array.
-   *
-   * @param int    $len How much to read
-   * @return string The data that has been read
-   * @throws TTransportException if cannot read any more data
-   */
-  abstract public function read($len);
-
-  /**
-   * Guarantees that the full amount of data is read.
-   *
-   * @return string The data, of exact length
-   * @throws TTransportException if cannot read data
-   */
-  public function readAll($len)
-  {
-    // return $this->read($len);
-
-    $data = '';
-    $got = 0;
-    while (($got = TStringFuncFactory::create()->strlen($data)) < $len) {
-      $data .= $this->read($len - $got);
-    }
-
-    return $data;
-  }
-
-  /**
-   * Writes the given data out.
-   *
-   * @param string $buf  The data to write
-   * @throws TTransportException if writing fails
-   */
-  abstract public function write($buf);
-
-  /**
-   * Flushes any pending data out of a buffer
-   *
-   * @throws TTransportException if a writing error occurs
-   */
-  public function flush() {}
-}
diff --git a/lib/php/lib/Transport/TBufferedTransport.php b/lib/php/lib/Transport/TBufferedTransport.php
new file mode 100644
index 0000000..253c5ac
--- /dev/null
+++ b/lib/php/lib/Transport/TBufferedTransport.php
@@ -0,0 +1,206 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Buffered transport. Stores data to an internal buffer that it doesn't
+ * actually write out until flush is called. For reading, we do a greedy
+ * read and then serve data out of the internal buffer.
+ *
+ * @package thrift.transport
+ */
+class TBufferedTransport extends TTransport
+{
+    /**
+     * The underlying transport
+     *
+     * @var TTransport
+     */
+    protected $transport_;
+
+    /**
+     * The receive buffer size
+     *
+     * @var int
+     */
+    protected $rBufSize_ = 512;
+
+    /**
+     * The write buffer size
+     *
+     * @var int
+     */
+    protected $wBufSize_ = 512;
+
+    /**
+     * The write buffer.
+     *
+     * @var string
+     */
+    protected $wBuf_ = '';
+
+    /**
+     * The read buffer.
+     *
+     * @var string
+     */
+    protected $rBuf_ = '';
+
+    /**
+     * Constructor. Creates a buffered transport around an underlying transport
+     */
+    public function __construct($transport, $rBufSize = 512, $wBufSize = 512)
+    {
+        $this->transport_ = $transport;
+        $this->rBufSize_ = $rBufSize;
+        $this->wBufSize_ = $wBufSize;
+    }
+
+    public function isOpen()
+    {
+        return $this->transport_->isOpen();
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @throws TTransportException
+     */
+    public function open()
+    {
+        $this->transport_->open();
+    }
+
+    public function close()
+    {
+        $this->transport_->close();
+    }
+
+    public function putBack($data)
+    {
+        if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+            $this->rBuf_ = $data;
+        } else {
+            $this->rBuf_ = ($data . $this->rBuf_);
+        }
+    }
+
+    /**
+     * The reason that we customize readAll here is that the majority of PHP
+     * streams are already internally buffered by PHP. The socket stream, for
+     * example, buffers internally and blocks if you call read with $len greater
+     * than the amount of data available, unlike recv() in C.
+     *
+     * Therefore, use the readAll method of the wrapped transport inside
+     * the buffered readAll.
+     *
+     * @throws TTransportException
+     */
+    public function readAll($len)
+    {
+        $have = TStringFuncFactory::create()->strlen($this->rBuf_);
+        if ($have == 0) {
+            $data = $this->transport_->readAll($len);
+        } elseif ($have < $len) {
+            $data = $this->rBuf_;
+            $this->rBuf_ = '';
+            $data .= $this->transport_->readAll($len - $have);
+        } elseif ($have == $len) {
+            $data = $this->rBuf_;
+            $this->rBuf_ = '';
+        } elseif ($have > $len) {
+            $data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+            $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+        }
+
+        return $data;
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @param int $len
+     * @return string
+     * @throws TTransportException
+     */
+    public function read($len)
+    {
+        if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+            $this->rBuf_ = $this->transport_->read($this->rBufSize_);
+        }
+
+        if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) {
+            $ret = $this->rBuf_;
+            $this->rBuf_ = '';
+
+            return $ret;
+        }
+
+        $ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+        $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+
+        return $ret;
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @param string $buf
+     * @throws TTransportException
+     */
+    public function write($buf)
+    {
+        $this->wBuf_ .= $buf;
+        if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) {
+            $out = $this->wBuf_;
+
+            // Note that we clear the internal wBuf_ prior to the underlying write
+            // to ensure we're in a sane state (i.e. internal buffer cleaned)
+            // if the underlying write throws up an exception
+            $this->wBuf_ = '';
+            $this->transport_->write($out);
+        }
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @throws TTransportException
+     */
+    public function flush()
+    {
+        if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) {
+            $out = $this->wBuf_;
+
+            // Note that we clear the internal wBuf_ prior to the underlying write
+            // to ensure we're in a sane state (i.e. internal buffer cleaned)
+            // if the underlying write throws up an exception
+            $this->wBuf_ = '';
+            $this->transport_->write($out);
+        }
+        $this->transport_->flush();
+    }
+}
diff --git a/lib/php/lib/Transport/TCurlClient.php b/lib/php/lib/Transport/TCurlClient.php
new file mode 100644
index 0000000..482b43b
--- /dev/null
+++ b/lib/php/lib/Transport/TCurlClient.php
@@ -0,0 +1,276 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * HTTP client for Thrift
+ *
+ * @package thrift.transport
+ */
+class TCurlClient extends TTransport
+{
+    private static $curlHandle;
+
+    /**
+     * The host to connect to
+     *
+     * @var string
+     */
+    protected $host_;
+
+    /**
+     * The port to connect on
+     *
+     * @var int
+     */
+    protected $port_;
+
+    /**
+     * The URI to request
+     *
+     * @var string
+     */
+    protected $uri_;
+
+    /**
+     * The scheme to use for the request, i.e. http, https
+     *
+     * @var string
+     */
+    protected $scheme_;
+
+    /**
+     * Buffer for the HTTP request data
+     *
+     * @var string
+     */
+    protected $request_;
+
+    /**
+     * Buffer for the HTTP response data.
+     *
+     * @var binary string
+     */
+    protected $response_;
+
+    /**
+     * Read timeout
+     *
+     * @var float
+     */
+    protected $timeout_;
+
+    /**
+     * http headers
+     *
+     * @var array
+     */
+    protected $headers_;
+
+    /**
+     * Make a new HTTP client.
+     *
+     * @param string $host
+     * @param int $port
+     * @param string $uri
+     */
+    public function __construct($host, $port = 80, $uri = '', $scheme = 'http')
+    {
+        if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
+            $uri = '/' . $uri;
+        }
+        $this->scheme_ = $scheme;
+        $this->host_ = $host;
+        $this->port_ = $port;
+        $this->uri_ = $uri;
+        $this->request_ = '';
+        $this->response_ = null;
+        $this->timeout_ = null;
+        $this->headers_ = array();
+    }
+
+    /**
+     * Set read timeout
+     *
+     * @param float $timeout
+     */
+    public function setTimeoutSecs($timeout)
+    {
+        $this->timeout_ = $timeout;
+    }
+
+    /**
+     * Whether this transport is open.
+     *
+     * @return boolean true if open
+     */
+    public function isOpen()
+    {
+        return true;
+    }
+
+    /**
+     * Open the transport for reading/writing
+     *
+     * @throws TTransportException if cannot open
+     */
+    public function open()
+    {
+    }
+
+    /**
+     * Close the transport.
+     */
+    public function close()
+    {
+        $this->request_ = '';
+        $this->response_ = null;
+    }
+
+    /**
+     * Read some data into the array.
+     *
+     * @param int $len How much to read
+     * @return string The data that has been read
+     * @throws TTransportException if cannot read any more data
+     */
+    public function read($len)
+    {
+        if ($len >= strlen($this->response_)) {
+            return $this->response_;
+        } else {
+            $ret = substr($this->response_, 0, $len);
+            $this->response_ = substr($this->response_, $len);
+
+            return $ret;
+        }
+    }
+
+    /**
+     * Guarantees that the full amount of data is read. Since TCurlClient gets entire payload at
+     * once, parent readAll cannot be used.
+     *
+     * @return string The data, of exact length
+     * @throws TTransportException if cannot read data
+     */
+    public function readAll($len)
+    {
+        $data = $this->read($len);
+
+        if (TStringFuncFactory::create()->strlen($data) !== $len) {
+            throw new TTransportException('TCurlClient could not read '.$len.' bytes');
+        }
+
+        return $data;
+    }
+
+    /**
+     * Writes some data into the pending buffer
+     *
+     * @param string $buf The data to write
+     * @throws TTransportException if writing fails
+     */
+    public function write($buf)
+    {
+        $this->request_ .= $buf;
+    }
+
+    /**
+     * Opens and sends the actual request over the HTTP connection
+     *
+     * @throws TTransportException if a writing error occurs
+     */
+    public function flush()
+    {
+        if (!self::$curlHandle) {
+            register_shutdown_function(array('Thrift\\Transport\\TCurlClient', 'closeCurlHandle'));
+            self::$curlHandle = curl_init();
+            curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true);
+            curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true);
+            curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
+            curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
+            curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true);
+            curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1);
+        }
+        // God, PHP really has some esoteric ways of doing simple things.
+        $host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : '');
+        $fullUrl = $this->scheme_ . "://" . $host . $this->uri_;
+
+        $headers = array();
+        $defaultHeaders = array('Accept' => 'application/x-thrift',
+            'Content-Type' => 'application/x-thrift',
+            'Content-Length' => TStringFuncFactory::create()->strlen($this->request_));
+        foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
+            $headers[] = "$key: $value";
+        }
+
+        curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers);
+
+        if ($this->timeout_ > 0) {
+            curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_);
+        }
+        curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_);
+        $this->request_ = '';
+
+        curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl);
+        $this->response_ = curl_exec(self::$curlHandle);
+        $responseError = curl_error(self::$curlHandle);
+
+        $code = curl_getinfo(self::$curlHandle, CURLINFO_HTTP_CODE);
+
+        // Handle non 200 status code / connect failure
+        if ($this->response_ === false || $code !== 200) {
+            curl_close(self::$curlHandle);
+            self::$curlHandle = null;
+            $this->response_ = null;
+            $error = 'TCurlClient: Could not connect to ' . $fullUrl;
+            if ($responseError) {
+                $error .= ', ' . $responseError;
+            }
+            if ($code) {
+                $error .= ', HTTP status code: ' . $code;
+            }
+            throw new TTransportException($error, TTransportException::UNKNOWN);
+        }
+    }
+
+    public static function closeCurlHandle()
+    {
+        try {
+            if (self::$curlHandle) {
+                curl_close(self::$curlHandle);
+                self::$curlHandle = null;
+            }
+        } catch (\Exception $x) {
+            error_log('There was an error closing the curl handle: ' . $x->getMessage());
+        }
+    }
+
+    public function addHeaders($headers)
+    {
+        $this->headers_ = array_merge($this->headers_, $headers);
+    }
+}
diff --git a/lib/php/lib/Transport/TFramedTransport.php b/lib/php/lib/Transport/TFramedTransport.php
new file mode 100644
index 0000000..39d1869
--- /dev/null
+++ b/lib/php/lib/Transport/TFramedTransport.php
@@ -0,0 +1,192 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Framed transport. Writes and reads data in chunks that are stamped with
+ * their length.
+ *
+ * @package thrift.transport
+ */
+class TFramedTransport extends TTransport
+{
+    /**
+     * Underlying transport object.
+     *
+     * @var TTransport
+     */
+    private $transport_;
+
+    /**
+     * Buffer for read data.
+     *
+     * @var string
+     */
+    private $rBuf_;
+
+    /**
+     * Buffer for queued output data
+     *
+     * @var string
+     */
+    private $wBuf_;
+
+    /**
+     * Whether to frame reads
+     *
+     * @var bool
+     */
+    private $read_;
+
+    /**
+     * Whether to frame writes
+     *
+     * @var bool
+     */
+    private $write_;
+
+    /**
+     * Constructor.
+     *
+     * @param TTransport $transport Underlying transport
+     */
+    public function __construct($transport = null, $read = true, $write = true)
+    {
+        $this->transport_ = $transport;
+        $this->read_ = $read;
+        $this->write_ = $write;
+    }
+
+    public function isOpen()
+    {
+        return $this->transport_->isOpen();
+    }
+
+    public function open()
+    {
+        $this->transport_->open();
+    }
+
+    public function close()
+    {
+        $this->transport_->close();
+    }
+
+    /**
+     * Reads from the buffer. When more data is required reads another entire
+     * chunk and serves future reads out of that.
+     *
+     * @param int $len How much data
+     */
+    public function read($len)
+    {
+        if (!$this->read_) {
+            return $this->transport_->read($len);
+        }
+
+        if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+            $this->readFrame();
+        }
+
+        // Just return full buff
+        if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) {
+            $out = $this->rBuf_;
+            $this->rBuf_ = null;
+
+            return $out;
+        }
+
+        // Return TStringFuncFactory::create()->substr
+        $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+        $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+
+        return $out;
+    }
+
+    /**
+     * Put previously read data back into the buffer
+     *
+     * @param string $data data to return
+     */
+    public function putBack($data)
+    {
+        if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+            $this->rBuf_ = $data;
+        } else {
+            $this->rBuf_ = ($data . $this->rBuf_);
+        }
+    }
+
+    /**
+     * Reads a chunk of data into the internal read buffer.
+     */
+    private function readFrame()
+    {
+        $buf = $this->transport_->readAll(4);
+        $val = unpack('N', $buf);
+        $sz = $val[1];
+
+        $this->rBuf_ = $this->transport_->readAll($sz);
+    }
+
+    /**
+     * Writes some data to the pending output buffer.
+     *
+     * @param string $buf The data
+     * @param int $len Limit of bytes to write
+     */
+    public function write($buf, $len = null)
+    {
+        if (!$this->write_) {
+            return $this->transport_->write($buf, $len);
+        }
+
+        if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) {
+            $buf = TStringFuncFactory::create()->substr($buf, 0, $len);
+        }
+        $this->wBuf_ .= $buf;
+    }
+
+    /**
+     * Writes the output buffer to the stream in the format of a 4-byte length
+     * followed by the actual data.
+     */
+    public function flush()
+    {
+        if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) {
+            return $this->transport_->flush();
+        }
+
+        $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_));
+        $out .= $this->wBuf_;
+
+        // Note that we clear the internal wBuf_ prior to the underlying write
+        // to ensure we're in a sane state (i.e. internal buffer cleaned)
+        // if the underlying write throws up an exception
+        $this->wBuf_ = '';
+        $this->transport_->write($out);
+        $this->transport_->flush();
+    }
+}
diff --git a/lib/php/lib/Transport/THttpClient.php b/lib/php/lib/Transport/THttpClient.php
new file mode 100644
index 0000000..0158809
--- /dev/null
+++ b/lib/php/lib/Transport/THttpClient.php
@@ -0,0 +1,258 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * HTTP client for Thrift
+ *
+ * @package thrift.transport
+ */
+class THttpClient extends TTransport
+{
+    /**
+     * The host to connect to
+     *
+     * @var string
+     */
+    protected $host_;
+
+    /**
+     * The port to connect on
+     *
+     * @var int
+     */
+    protected $port_;
+
+    /**
+     * The URI to request
+     *
+     * @var string
+     */
+    protected $uri_;
+
+    /**
+     * The scheme to use for the request, i.e. http, https
+     *
+     * @var string
+     */
+    protected $scheme_;
+
+    /**
+     * Buffer for the HTTP request data
+     *
+     * @var string
+     */
+    protected $buf_;
+
+    /**
+     * Input socket stream.
+     *
+     * @var resource
+     */
+    protected $handle_;
+
+    /**
+     * Read timeout
+     *
+     * @var float
+     */
+    protected $timeout_;
+
+    /**
+     * http headers
+     *
+     * @var array
+     */
+    protected $headers_;
+
+    /**
+     * Context additional options
+     *
+     * @var array
+     */
+    protected $context_;
+
+    /**
+     * Make a new HTTP client.
+     *
+     * @param string $host
+     * @param int    $port
+     * @param string $uri
+     * @param string $scheme
+     * @param array  $context
+     */
+    public function __construct($host, $port = 80, $uri = '', $scheme = 'http', array $context = array())
+    {
+        if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
+            $uri = '/' . $uri;
+        }
+        $this->scheme_ = $scheme;
+        $this->host_ = $host;
+        $this->port_ = $port;
+        $this->uri_ = $uri;
+        $this->buf_ = '';
+        $this->handle_ = null;
+        $this->timeout_ = null;
+        $this->headers_ = array();
+        $this->context_ = $context;
+    }
+
+    /**
+     * Set read timeout
+     *
+     * @param float $timeout
+     */
+    public function setTimeoutSecs($timeout)
+    {
+        $this->timeout_ = $timeout;
+    }
+
+    /**
+     * Whether this transport is open.
+     *
+     * @return boolean true if open
+     */
+    public function isOpen()
+    {
+        return true;
+    }
+
+    /**
+     * Open the transport for reading/writing
+     *
+     * @throws TTransportException if cannot open
+     */
+    public function open()
+    {
+    }
+
+    /**
+     * Close the transport.
+     */
+    public function close()
+    {
+        if ($this->handle_) {
+            @fclose($this->handle_);
+            $this->handle_ = null;
+        }
+    }
+
+    /**
+     * Read some data into the array.
+     *
+     * @param int $len How much to read
+     * @return string The data that has been read
+     * @throws TTransportException if cannot read any more data
+     */
+    public function read($len)
+    {
+        $data = @fread($this->handle_, $len);
+        if ($data === false || $data === '') {
+            $md = stream_get_meta_data($this->handle_);
+            if ($md['timed_out']) {
+                throw new TTransportException(
+                    'THttpClient: timed out reading ' . $len . ' bytes from ' .
+                    $this->host_ . ':' . $this->port_ . $this->uri_,
+                    TTransportException::TIMED_OUT
+                );
+            } else {
+                throw new TTransportException(
+                    'THttpClient: Could not read ' . $len . ' bytes from ' .
+                    $this->host_ . ':' . $this->port_ . $this->uri_,
+                    TTransportException::UNKNOWN
+                );
+            }
+        }
+
+        return $data;
+    }
+
+    /**
+     * Writes some data into the pending buffer
+     *
+     * @param string $buf The data to write
+     * @throws TTransportException if writing fails
+     */
+    public function write($buf)
+    {
+        $this->buf_ .= $buf;
+    }
+
+    /**
+     * Opens and sends the actual request over the HTTP connection
+     *
+     * @throws TTransportException if a writing error occurs
+     */
+    public function flush()
+    {
+        // God, PHP really has some esoteric ways of doing simple things.
+        $host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : '');
+
+        $headers = array();
+        $defaultHeaders = array('Host' => $host,
+            'Accept' => 'application/x-thrift',
+            'User-Agent' => 'PHP/THttpClient',
+            'Content-Type' => 'application/x-thrift',
+            'Content-Length' => TStringFuncFactory::create()->strlen($this->buf_));
+        foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
+            $headers[] = "$key: $value";
+        }
+
+        $options = $this->context_;
+
+        $baseHttpOptions = isset($options["http"]) ? $options["http"] : array();
+
+        $httpOptions = $baseHttpOptions + array('method' => 'POST',
+            'header' => implode("\r\n", $headers),
+            'max_redirects' => 1,
+            'content' => $this->buf_);
+        if ($this->timeout_ > 0) {
+            $httpOptions['timeout'] = $this->timeout_;
+        }
+        $this->buf_ = '';
+
+        $options["http"] = $httpOptions;
+        $contextid = stream_context_create($options);
+        $this->handle_ = @fopen(
+            $this->scheme_ . '://' . $host . $this->uri_,
+            'r',
+            false,
+            $contextid
+        );
+
+        // Connect failed?
+        if ($this->handle_ === false) {
+            $this->handle_ = null;
+            $error = 'THttpClient: Could not connect to ' . $host . $this->uri_;
+            throw new TTransportException($error, TTransportException::NOT_OPEN);
+        }
+    }
+
+    public function addHeaders($headers)
+    {
+        $this->headers_ = array_merge($this->headers_, $headers);
+    }
+}
diff --git a/lib/php/lib/Transport/TMemoryBuffer.php b/lib/php/lib/Transport/TMemoryBuffer.php
new file mode 100644
index 0000000..fee03a2
--- /dev/null
+++ b/lib/php/lib/Transport/TMemoryBuffer.php
@@ -0,0 +1,106 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * A memory buffer is a tranpsort that simply reads from and writes to an
+ * in-memory string buffer. Anytime you call write on it, the data is simply
+ * placed into a buffer, and anytime you call read, data is read from that
+ * buffer.
+ *
+ * @package thrift.transport
+ */
+class TMemoryBuffer extends TTransport
+{
+    /**
+     * Constructor. Optionally pass an initial value
+     * for the buffer.
+     */
+    public function __construct($buf = '')
+    {
+        $this->buf_ = $buf;
+    }
+
+    protected $buf_ = '';
+
+    public function isOpen()
+    {
+        return true;
+    }
+
+    public function open()
+    {
+    }
+
+    public function close()
+    {
+    }
+
+    public function write($buf)
+    {
+        $this->buf_ .= $buf;
+    }
+
+    public function read($len)
+    {
+        $bufLength = TStringFuncFactory::create()->strlen($this->buf_);
+
+        if ($bufLength === 0) {
+            throw new TTransportException(
+                'TMemoryBuffer: Could not read ' .
+                $len . ' bytes from buffer.',
+                TTransportException::UNKNOWN
+            );
+        }
+
+        if ($bufLength <= $len) {
+            $ret = $this->buf_;
+            $this->buf_ = '';
+
+            return $ret;
+        }
+
+        $ret = TStringFuncFactory::create()->substr($this->buf_, 0, $len);
+        $this->buf_ = TStringFuncFactory::create()->substr($this->buf_, $len);
+
+        return $ret;
+    }
+
+    public function getBuffer()
+    {
+        return $this->buf_;
+    }
+
+    public function available()
+    {
+        return TStringFuncFactory::create()->strlen($this->buf_);
+    }
+
+    public function putBack($data)
+    {
+        $this->buf_ = $data . $this->buf_;
+    }
+}
diff --git a/lib/php/lib/Thrift/Transport/TNullTransport.php b/lib/php/lib/Transport/TNullTransport.php
similarity index 78%
rename from lib/php/lib/Thrift/Transport/TNullTransport.php
rename to lib/php/lib/Transport/TNullTransport.php
index feeb7a4..7e086b6 100644
--- a/lib/php/lib/Thrift/Transport/TNullTransport.php
+++ b/lib/php/lib/Transport/TNullTransport.php
@@ -32,20 +32,25 @@
  */
 class TNullTransport extends TTransport
 {
-  public function isOpen()
-  {
-    return true;
-  }
+    public function isOpen()
+    {
+        return true;
+    }
 
-  public function open() {}
+    public function open()
+    {
+    }
 
-  public function close() {}
+    public function close()
+    {
+    }
 
-  public function read($len)
-  {
-    throw new TTransportException("Can't read from TNullTransport.");
-  }
+    public function read($len)
+    {
+        throw new TTransportException("Can't read from TNullTransport.");
+    }
 
-  public function write($buf) {}
-
+    public function write($buf)
+    {
+    }
 }
diff --git a/lib/php/lib/Transport/TPhpStream.php b/lib/php/lib/Transport/TPhpStream.php
new file mode 100644
index 0000000..42823ff
--- /dev/null
+++ b/lib/php/lib/Transport/TPhpStream.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Php stream transport. Reads to and writes from the php standard streams
+ * php://input and php://output
+ *
+ * @package thrift.transport
+ */
+class TPhpStream extends TTransport
+{
+    const MODE_R = 1;
+    const MODE_W = 2;
+
+    private $inStream_ = null;
+
+    private $outStream_ = null;
+
+    private $read_ = false;
+
+    private $write_ = false;
+
+    public function __construct($mode)
+    {
+        $this->read_ = $mode & self::MODE_R;
+        $this->write_ = $mode & self::MODE_W;
+    }
+
+    public function open()
+    {
+        if ($this->read_) {
+            $this->inStream_ = @fopen(self::inStreamName(), 'r');
+            if (!is_resource($this->inStream_)) {
+                throw new TException('TPhpStream: Could not open php://input');
+            }
+        }
+        if ($this->write_) {
+            $this->outStream_ = @fopen('php://output', 'w');
+            if (!is_resource($this->outStream_)) {
+                throw new TException('TPhpStream: Could not open php://output');
+            }
+        }
+    }
+
+    public function close()
+    {
+        if ($this->read_) {
+            @fclose($this->inStream_);
+            $this->inStream_ = null;
+        }
+        if ($this->write_) {
+            @fclose($this->outStream_);
+            $this->outStream_ = null;
+        }
+    }
+
+    public function isOpen()
+    {
+        return
+            (!$this->read_ || is_resource($this->inStream_)) &&
+            (!$this->write_ || is_resource($this->outStream_));
+    }
+
+    public function read($len)
+    {
+        $data = @fread($this->inStream_, $len);
+        if ($data === false || $data === '') {
+            throw new TException('TPhpStream: Could not read ' . $len . ' bytes');
+        }
+
+        return $data;
+    }
+
+    public function write($buf)
+    {
+        while (TStringFuncFactory::create()->strlen($buf) > 0) {
+            $got = @fwrite($this->outStream_, $buf);
+            if ($got === 0 || $got === false) {
+                throw new TException(
+                    'TPhpStream: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes'
+                );
+            }
+            $buf = TStringFuncFactory::create()->substr($buf, $got);
+        }
+    }
+
+    public function flush()
+    {
+        @fflush($this->outStream_);
+    }
+
+    private static function inStreamName()
+    {
+        if (php_sapi_name() == 'cli') {
+            return 'php://stdin';
+        }
+
+        return 'php://input';
+    }
+}
diff --git a/lib/php/lib/Transport/TSSLSocket.php b/lib/php/lib/Transport/TSSLSocket.php
new file mode 100644
index 0000000..b4a0adb
--- /dev/null
+++ b/lib/php/lib/Transport/TSSLSocket.php
@@ -0,0 +1,117 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Sockets implementation of the TTransport interface.
+ *
+ * @package thrift.transport
+ */
+class TSSLSocket extends TSocket
+{
+    /**
+     * Remote port
+     *
+     * @var resource
+     */
+    protected $context_ = null;
+
+    /**
+     * Socket constructor
+     *
+     * @param string $host Remote hostname
+     * @param int $port Remote port
+     * @param resource $context Stream context
+     * @param bool $persist Whether to use a persistent socket
+     * @param string $debugHandler Function to call for error logging
+     */
+    public function __construct(
+        $host = 'localhost',
+        $port = 9090,
+        $context = null,
+        $debugHandler = null
+    ) {
+        $this->host_ = $this->getSSLHost($host);
+        $this->port_ = $port;
+        $this->context_ = $context;
+        $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
+    }
+
+    /**
+     * Creates a host name with SSL transport protocol
+     * if no transport protocol already specified in
+     * the host name.
+     *
+     * @param string $host Host to listen on
+     * @return string $host   Host name with transport protocol
+     */
+    private function getSSLHost($host)
+    {
+        $transport_protocol_loc = strpos($host, "://");
+        if ($transport_protocol_loc === false) {
+            $host = 'ssl://' . $host;
+        }
+        return $host;
+    }
+
+    /**
+     * Connects the socket.
+     */
+    public function open()
+    {
+        if ($this->isOpen()) {
+            throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
+        }
+
+        if (empty($this->host_)) {
+            throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
+        }
+
+        if ($this->port_ <= 0) {
+            throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
+        }
+
+        $this->handle_ = @stream_socket_client(
+            $this->host_ . ':' . $this->port_,
+            $errno,
+            $errstr,
+            $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000),
+            STREAM_CLIENT_CONNECT,
+            $this->context_
+        );
+
+        // Connect failed?
+        if ($this->handle_ === false) {
+            $error = 'TSocket: Could not connect to ' .
+                $this->host_ . ':' . $this->port_ . ' (' . $errstr . ' [' . $errno . '])';
+            if ($this->debug_) {
+                call_user_func($this->debugHandler_, $error);
+            }
+            throw new TException($error);
+        }
+    }
+}
diff --git a/lib/php/lib/Transport/TSocket.php b/lib/php/lib/Transport/TSocket.php
new file mode 100644
index 0000000..5147efa
--- /dev/null
+++ b/lib/php/lib/Transport/TSocket.php
@@ -0,0 +1,366 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Sockets implementation of the TTransport interface.
+ *
+ * @package thrift.transport
+ */
+class TSocket extends TTransport
+{
+    /**
+     * Handle to PHP socket
+     *
+     * @var resource
+     */
+    protected $handle_ = null;
+
+    /**
+     * Remote hostname
+     *
+     * @var string
+     */
+    protected $host_ = 'localhost';
+
+    /**
+     * Remote port
+     *
+     * @var int
+     */
+    protected $port_ = '9090';
+
+    /**
+     * Send timeout in seconds.
+     *
+     * Combined with sendTimeoutUsec this is used for send timeouts.
+     *
+     * @var int
+     */
+    protected $sendTimeoutSec_ = 0;
+
+    /**
+     * Send timeout in microseconds.
+     *
+     * Combined with sendTimeoutSec this is used for send timeouts.
+     *
+     * @var int
+     */
+    protected $sendTimeoutUsec_ = 100000;
+
+    /**
+     * Recv timeout in seconds
+     *
+     * Combined with recvTimeoutUsec this is used for recv timeouts.
+     *
+     * @var int
+     */
+    protected $recvTimeoutSec_ = 0;
+
+    /**
+     * Recv timeout in microseconds
+     *
+     * Combined with recvTimeoutSec this is used for recv timeouts.
+     *
+     * @var int
+     */
+    protected $recvTimeoutUsec_ = 750000;
+
+    /**
+     * Persistent socket or plain?
+     *
+     * @var bool
+     */
+    protected $persist_ = false;
+
+    /**
+     * Debugging on?
+     *
+     * @var bool
+     */
+    protected $debug_ = false;
+
+    /**
+     * Debug handler
+     *
+     * @var mixed
+     */
+    protected $debugHandler_ = null;
+
+    /**
+     * Socket constructor
+     *
+     * @param string $host Remote hostname
+     * @param int $port Remote port
+     * @param bool $persist Whether to use a persistent socket
+     * @param string $debugHandler Function to call for error logging
+     */
+    public function __construct(
+        $host = 'localhost',
+        $port = 9090,
+        $persist = false,
+        $debugHandler = null
+    ) {
+        $this->host_ = $host;
+        $this->port_ = $port;
+        $this->persist_ = $persist;
+        $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
+    }
+
+    /**
+     * @param resource $handle
+     * @return void
+     */
+    public function setHandle($handle)
+    {
+        $this->handle_ = $handle;
+        stream_set_blocking($this->handle_, false);
+    }
+
+    /**
+     * Sets the send timeout.
+     *
+     * @param int $timeout Timeout in milliseconds.
+     */
+    public function setSendTimeout($timeout)
+    {
+        $this->sendTimeoutSec_ = floor($timeout / 1000);
+        $this->sendTimeoutUsec_ =
+            ($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000;
+    }
+
+    /**
+     * Sets the receive timeout.
+     *
+     * @param int $timeout Timeout in milliseconds.
+     */
+    public function setRecvTimeout($timeout)
+    {
+        $this->recvTimeoutSec_ = floor($timeout / 1000);
+        $this->recvTimeoutUsec_ =
+            ($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000;
+    }
+
+    /**
+     * Sets debugging output on or off
+     *
+     * @param bool $debug
+     */
+    public function setDebug($debug)
+    {
+        $this->debug_ = $debug;
+    }
+
+    /**
+     * Get the host that this socket is connected to
+     *
+     * @return string host
+     */
+    public function getHost()
+    {
+        return $this->host_;
+    }
+
+    /**
+     * Get the remote port that this socket is connected to
+     *
+     * @return int port
+     */
+    public function getPort()
+    {
+        return $this->port_;
+    }
+
+    /**
+     * Tests whether this is open
+     *
+     * @return bool true if the socket is open
+     */
+    public function isOpen()
+    {
+        return is_resource($this->handle_);
+    }
+
+    /**
+     * Connects the socket.
+     */
+    public function open()
+    {
+        if ($this->isOpen()) {
+            throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
+        }
+
+        if (empty($this->host_)) {
+            throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
+        }
+
+        if ($this->port_ <= 0) {
+            throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
+        }
+
+        if ($this->persist_) {
+            $this->handle_ = @pfsockopen(
+                $this->host_,
+                $this->port_,
+                $errno,
+                $errstr,
+                $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000)
+            );
+        } else {
+            $this->handle_ = @fsockopen(
+                $this->host_,
+                $this->port_,
+                $errno,
+                $errstr,
+                $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000)
+            );
+        }
+
+        // Connect failed?
+        if ($this->handle_ === false) {
+            $error = 'TSocket: Could not connect to ' .
+                $this->host_ . ':' . $this->port_ . ' (' . $errstr . ' [' . $errno . '])';
+            if ($this->debug_) {
+                call_user_func($this->debugHandler_, $error);
+            }
+            throw new TException($error);
+        }
+
+        if (function_exists('socket_import_stream') && function_exists('socket_set_option')) {
+            $socket = socket_import_stream($this->handle_);
+            socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);
+        }
+    }
+
+    /**
+     * Closes the socket.
+     */
+    public function close()
+    {
+        @fclose($this->handle_);
+        $this->handle_ = null;
+    }
+
+    /**
+     * Read from the socket at most $len bytes.
+     *
+     * This method will not wait for all the requested data, it will return as
+     * soon as any data is received.
+     *
+     * @param int $len Maximum number of bytes to read.
+     * @return string Binary data
+     */
+    public function read($len)
+    {
+        $null = null;
+        $read = array($this->handle_);
+        $readable = @stream_select(
+            $read,
+            $null,
+            $null,
+            $this->recvTimeoutSec_,
+            $this->recvTimeoutUsec_
+        );
+
+        if ($readable > 0) {
+            $data = fread($this->handle_, $len);
+            if ($data === false) {
+                throw new TTransportException('TSocket: Could not read ' . $len . ' bytes from ' .
+                    $this->host_ . ':' . $this->port_);
+            } elseif ($data == '' && feof($this->handle_)) {
+                throw new TTransportException('TSocket read 0 bytes');
+            }
+
+            return $data;
+        } elseif ($readable === 0) {
+            throw new TTransportException('TSocket: timed out reading ' . $len . ' bytes from ' .
+                $this->host_ . ':' . $this->port_);
+        } else {
+            throw new TTransportException('TSocket: Could not read ' . $len . ' bytes from ' .
+                $this->host_ . ':' . $this->port_);
+        }
+    }
+
+    /**
+     * Write to the socket.
+     *
+     * @param string $buf The data to write
+     */
+    public function write($buf)
+    {
+        $null = null;
+        $write = array($this->handle_);
+
+        // keep writing until all the data has been written
+        while (TStringFuncFactory::create()->strlen($buf) > 0) {
+            // wait for stream to become available for writing
+            $writable = @stream_select(
+                $null,
+                $write,
+                $null,
+                $this->sendTimeoutSec_,
+                $this->sendTimeoutUsec_
+            );
+            if ($writable > 0) {
+                // write buffer to stream
+                $written = fwrite($this->handle_, $buf);
+                if ($written === -1 || $written === false) {
+                    throw new TTransportException(
+                        'TSocket: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes ' .
+                        $this->host_ . ':' . $this->port_
+                    );
+                }
+                // determine how much of the buffer is left to write
+                $buf = TStringFuncFactory::create()->substr($buf, $written);
+            } elseif ($writable === 0) {
+                throw new TTransportException(
+                    'TSocket: timed out writing ' . TStringFuncFactory::create()->strlen($buf) . ' bytes from ' .
+                    $this->host_ . ':' . $this->port_
+                );
+            } else {
+                throw new TTransportException(
+                    'TSocket: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes ' .
+                    $this->host_ . ':' . $this->port_
+                );
+            }
+        }
+    }
+
+    /**
+     * Flush output to the socket.
+     *
+     * Since read(), readAll() and write() operate on the sockets directly,
+     * this is a no-op
+     *
+     * If you wish to have flushable buffering behaviour, wrap this TSocket
+     * in a TBufferedTransport.
+     */
+    public function flush()
+    {
+        // no-op
+    }
+}
diff --git a/lib/php/lib/Transport/TSocketPool.php b/lib/php/lib/Transport/TSocketPool.php
new file mode 100644
index 0000000..cb9e8dd
--- /dev/null
+++ b/lib/php/lib/Transport/TSocketPool.php
@@ -0,0 +1,310 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+
+/**
+ * This library makes use of APC cache to make hosts as down in a web
+ * environment. If you are running from the CLI or on a system without APC
+ * installed, then these null functions will step in and act like cache
+ * misses.
+ */
+if (!function_exists('apc_fetch')) {
+    function apc_fetch($key)
+    {
+        return false;
+    }
+
+    function apc_store($key, $var, $ttl = 0)
+    {
+        return false;
+    }
+}
+
+/**
+ * Sockets implementation of the TTransport interface that allows connection
+ * to a pool of servers.
+ *
+ * @package thrift.transport
+ */
+class TSocketPool extends TSocket
+{
+    /**
+     * Remote servers. Array of associative arrays with 'host' and 'port' keys
+     */
+    private $servers_ = array();
+
+    /**
+     * How many times to retry each host in connect
+     *
+     * @var int
+     */
+    private $numRetries_ = 1;
+
+    /**
+     * Retry interval in seconds, how long to not try a host if it has been
+     * marked as down.
+     *
+     * @var int
+     */
+    private $retryInterval_ = 60;
+
+    /**
+     * Max consecutive failures before marking a host down.
+     *
+     * @var int
+     */
+    private $maxConsecutiveFailures_ = 1;
+
+    /**
+     * Try hosts in order? or Randomized?
+     *
+     * @var bool
+     */
+    private $randomize_ = true;
+
+    /**
+     * Always try last host, even if marked down?
+     *
+     * @var bool
+     */
+    private $alwaysTryLast_ = true;
+
+    /**
+     * Socket pool constructor
+     *
+     * @param array $hosts List of remote hostnames
+     * @param mixed $ports Array of remote ports, or a single common port
+     * @param bool $persist Whether to use a persistent socket
+     * @param mixed $debugHandler Function for error logging
+     */
+    public function __construct(
+        $hosts = array('localhost'),
+        $ports = array(9090),
+        $persist = false,
+        $debugHandler = null
+    ) {
+        parent::__construct(null, 0, $persist, $debugHandler);
+
+        if (!is_array($ports)) {
+            $port = $ports;
+            $ports = array();
+            foreach ($hosts as $key => $val) {
+                $ports[$key] = $port;
+            }
+        }
+
+        foreach ($hosts as $key => $host) {
+            $this->servers_ [] = array('host' => $host,
+                'port' => $ports[$key]);
+        }
+    }
+
+    /**
+     * Add a server to the pool
+     *
+     * This function does not prevent you from adding a duplicate server entry.
+     *
+     * @param string $host hostname or IP
+     * @param int $port port
+     */
+    public function addServer($host, $port)
+    {
+        $this->servers_[] = array('host' => $host, 'port' => $port);
+    }
+
+    /**
+     * Sets how many time to keep retrying a host in the connect function.
+     *
+     * @param int $numRetries
+     */
+    public function setNumRetries($numRetries)
+    {
+        $this->numRetries_ = $numRetries;
+    }
+
+    /**
+     * Sets how long to wait until retrying a host if it was marked down
+     *
+     * @param int $numRetries
+     */
+    public function setRetryInterval($retryInterval)
+    {
+        $this->retryInterval_ = $retryInterval;
+    }
+
+    /**
+     * Sets how many time to keep retrying a host before marking it as down.
+     *
+     * @param int $numRetries
+     */
+    public function setMaxConsecutiveFailures($maxConsecutiveFailures)
+    {
+        $this->maxConsecutiveFailures_ = $maxConsecutiveFailures;
+    }
+
+    /**
+     * Turns randomization in connect order on or off.
+     *
+     * @param bool $randomize
+     */
+    public function setRandomize($randomize)
+    {
+        $this->randomize_ = $randomize;
+    }
+
+    /**
+     * Whether to always try the last server.
+     *
+     * @param bool $alwaysTryLast
+     */
+    public function setAlwaysTryLast($alwaysTryLast)
+    {
+        $this->alwaysTryLast_ = $alwaysTryLast;
+    }
+
+    /**
+     * Connects the socket by iterating through all the servers in the pool
+     * and trying to find one that works.
+     */
+    public function open()
+    {
+        // Check if we want order randomization
+        if ($this->randomize_) {
+            shuffle($this->servers_);
+        }
+
+        // Count servers to identify the "last" one
+        $numServers = count($this->servers_);
+
+        for ($i = 0; $i < $numServers; ++$i) {
+            // This extracts the $host and $port variables
+            extract($this->servers_[$i]);
+
+            // Check APC cache for a record of this server being down
+            $failtimeKey = 'thrift_failtime:' . $host . ':' . $port . '~';
+
+            // Cache miss? Assume it's OK
+            $lastFailtime = apc_fetch($failtimeKey);
+            if ($lastFailtime === false) {
+                $lastFailtime = 0;
+            }
+
+            $retryIntervalPassed = false;
+
+            // Cache hit...make sure enough the retry interval has elapsed
+            if ($lastFailtime > 0) {
+                $elapsed = time() - $lastFailtime;
+                if ($elapsed > $this->retryInterval_) {
+                    $retryIntervalPassed = true;
+                    if ($this->debug_) {
+                        call_user_func(
+                            $this->debugHandler_,
+                            'TSocketPool: retryInterval ' .
+                            '(' . $this->retryInterval_ . ') ' .
+                            'has passed for host ' . $host . ':' . $port
+                        );
+                    }
+                }
+            }
+
+            // Only connect if not in the middle of a fail interval, OR if this
+            // is the LAST server we are trying, just hammer away on it
+            $isLastServer = false;
+            if ($this->alwaysTryLast_) {
+                $isLastServer = ($i == ($numServers - 1));
+            }
+
+            if (($lastFailtime === 0) ||
+                ($isLastServer) ||
+                ($lastFailtime > 0 && $retryIntervalPassed)) {
+                // Set underlying TSocket params to this one
+                $this->host_ = $host;
+                $this->port_ = $port;
+
+                // Try up to numRetries_ connections per server
+                for ($attempt = 0; $attempt < $this->numRetries_; $attempt++) {
+                    try {
+                        // Use the underlying TSocket open function
+                        parent::open();
+
+                        // Only clear the failure counts if required to do so
+                        if ($lastFailtime > 0) {
+                            apc_store($failtimeKey, 0);
+                        }
+
+                        // Successful connection, return now
+                        return;
+                    } catch (TException $tx) {
+                        // Connection failed
+                    }
+                }
+
+                // Mark failure of this host in the cache
+                $consecfailsKey = 'thrift_consecfails:' . $host . ':' . $port . '~';
+
+                // Ignore cache misses
+                $consecfails = apc_fetch($consecfailsKey);
+                if ($consecfails === false) {
+                    $consecfails = 0;
+                }
+
+                // Increment by one
+                $consecfails++;
+
+                // Log and cache this failure
+                if ($consecfails >= $this->maxConsecutiveFailures_) {
+                    if ($this->debug_) {
+                        call_user_func(
+                            $this->debugHandler_,
+                            'TSocketPool: marking ' . $host . ':' . $port .
+                            ' as down for ' . $this->retryInterval_ . ' secs ' .
+                            'after ' . $consecfails . ' failed attempts.'
+                        );
+                    }
+                    // Store the failure time
+                    apc_store($failtimeKey, time());
+
+                    // Clear the count of consecutive failures
+                    apc_store($consecfailsKey, 0);
+                } else {
+                    apc_store($consecfailsKey, $consecfails);
+                }
+            }
+        }
+
+        // Oh no; we failed them all. The system is totally ill!
+        $error = 'TSocketPool: All hosts in pool are down. ';
+        $hosts = array();
+        foreach ($this->servers_ as $server) {
+            $hosts [] = $server['host'] . ':' . $server['port'];
+        }
+        $hostlist = implode(',', $hosts);
+        $error .= '(' . $hostlist . ')';
+        if ($this->debug_) {
+            call_user_func($this->debugHandler_, $error);
+        }
+        throw new TException($error);
+    }
+}
diff --git a/lib/php/lib/Transport/TTransport.php b/lib/php/lib/Transport/TTransport.php
new file mode 100644
index 0000000..35921c6
--- /dev/null
+++ b/lib/php/lib/Transport/TTransport.php
@@ -0,0 +1,98 @@
+<?php
+/*
+ * 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.
+ *
+ * @package thrift.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Base interface for a transport agent.
+ *
+ * @package thrift.transport
+ */
+abstract class TTransport
+{
+    /**
+     * Whether this transport is open.
+     *
+     * @return boolean true if open
+     */
+    abstract public function isOpen();
+
+    /**
+     * Open the transport for reading/writing
+     *
+     * @throws TTransportException if cannot open
+     */
+    abstract public function open();
+
+    /**
+     * Close the transport.
+     */
+    abstract public function close();
+
+    /**
+     * Read some data into the array.
+     *
+     * @param int $len How much to read
+     * @return string The data that has been read
+     * @throws TTransportException if cannot read any more data
+     */
+    abstract public function read($len);
+
+    /**
+     * Guarantees that the full amount of data is read.
+     *
+     * @return string The data, of exact length
+     * @throws TTransportException if cannot read data
+     */
+    public function readAll($len)
+    {
+        // return $this->read($len);
+
+        $data = '';
+        $got = 0;
+        while (($got = TStringFuncFactory::create()->strlen($data)) < $len) {
+            $data .= $this->read($len - $got);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Writes the given data out.
+     *
+     * @param string $buf The data to write
+     * @throws TTransportException if writing fails
+     */
+    abstract public function write($buf);
+
+    /**
+     * Flushes any pending data out of a buffer
+     *
+     * @throws TTransportException if a writing error occurs
+     */
+    public function flush()
+    {
+    }
+}
diff --git a/lib/php/lib/Thrift/Type/TConstant.php b/lib/php/lib/Type/TConstant.php
similarity index 91%
rename from lib/php/lib/Thrift/Type/TConstant.php
rename to lib/php/lib/Type/TConstant.php
index 7c8eceb..215da4a 100644
--- a/lib/php/lib/Thrift/Type/TConstant.php
+++ b/lib/php/lib/Type/TConstant.php
@@ -30,7 +30,9 @@
     /**
      * Don't instanciate this class
      */
-    protected function __construct() {}
+    protected function __construct()
+    {
+    }
 
     /**
      * Get a constant value
@@ -41,8 +43,8 @@
     {
         if (is_null(static::$$constant)) {
             static::$$constant = call_user_func(
-                    sprintf('static::init_%s', $constant)
-                );
+                sprintf('static::init_%s', $constant)
+            );
         }
 
         return static::$$constant;
diff --git a/lib/php/lib/Thrift/Type/TMessageType.php b/lib/php/lib/Type/TMessageType.php
similarity index 90%
rename from lib/php/lib/Thrift/Type/TMessageType.php
rename to lib/php/lib/Type/TMessageType.php
index bff224f..dc9ae62 100644
--- a/lib/php/lib/Thrift/Type/TMessageType.php
+++ b/lib/php/lib/Type/TMessageType.php
@@ -27,8 +27,8 @@
  */
 class TMessageType
 {
-  const CALL  = 1;
-  const REPLY = 2;
-  const EXCEPTION = 3;
-  const ONEWAY = 4;
+    const CALL  = 1;
+    const REPLY = 2;
+    const EXCEPTION = 3;
+    const ONEWAY = 4;
 }
diff --git a/lib/php/lib/Thrift/Type/TType.php b/lib/php/lib/Type/TType.php
similarity index 68%
rename from lib/php/lib/Thrift/Type/TType.php
rename to lib/php/lib/Type/TType.php
index 71219c2..3fdb15f 100644
--- a/lib/php/lib/Thrift/Type/TType.php
+++ b/lib/php/lib/Type/TType.php
@@ -27,21 +27,21 @@
  */
 class TType
 {
-  const STOP   = 0;
-  const VOID   = 1;
-  const BOOL   = 2;
-  const BYTE   = 3;
-  const I08    = 3;
-  const DOUBLE = 4;
-  const I16    = 6;
-  const I32    = 8;
-  const I64    = 10;
-  const STRING = 11;
-  const UTF7   = 11;
-  const STRUCT = 12;
-  const MAP    = 13;
-  const SET    = 14;
-  const LST    = 15;    // N.B. cannot use LIST keyword in PHP!
-  const UTF8   = 16;
-  const UTF16  = 17;
+    const STOP   = 0;
+    const VOID   = 1;
+    const BOOL   = 2;
+    const BYTE   = 3;
+    const I08    = 3;
+    const DOUBLE = 4;
+    const I16    = 6;
+    const I32    = 8;
+    const I64    = 10;
+    const STRING = 11;
+    const UTF7   = 11;
+    const STRUCT = 12;
+    const MAP    = 13;
+    const SET    = 14;
+    const LST    = 15;    // N.B. cannot use LIST keyword in PHP!
+    const UTF8   = 16;
+    const UTF16  = 17;
 }
diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
index 75ef2ec..63c8905 100644
--- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
+++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
@@ -305,7 +305,7 @@
 
   void skip(size_t len) {
     while (len) {
-      size_t chunk_size = std::min(len, buffer_used);
+      size_t chunk_size = (std::min)(len, buffer_used);
       if (chunk_size) {
         buffer_ptr = reinterpret_cast<char*>(buffer_ptr) + chunk_size;
         buffer_used -= chunk_size;
@@ -318,7 +318,7 @@
 
   void readBytes(void* buf, size_t len) {
     while (len) {
-      size_t chunk_size = std::min(len, buffer_used);
+      size_t chunk_size = (std::min)(len, buffer_used);
       if (chunk_size) {
         memcpy(buf, buffer_ptr, chunk_size);
         buffer_ptr = reinterpret_cast<char*>(buffer_ptr) + chunk_size;
@@ -537,6 +537,7 @@
       }
 
       zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false);
+      ZVAL_DEREF(spec);
       if (EG(exception)) {
         zend_object *ex = EG(exception);
         EG(exception) = nullptr;
@@ -699,6 +700,9 @@
 
 static
 void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* value, HashTable* fieldspec) {
+  if (value) {
+    ZVAL_DEREF(value);
+  }
   // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload.
   switch (thrift_typeID) {
     case T_STOP:
@@ -709,6 +713,9 @@
         throw_tprotocolexception("Attempt to send non-object type as a T_STRUCT", INVALID_DATA);
       }
       zval* spec = zend_read_static_property(Z_OBJCE_P(value), "_TSPEC", sizeof("_TSPEC")-1, true);
+      if (spec && Z_TYPE_P(spec) == IS_REFERENCE) {
+        ZVAL_DEREF(spec);
+      }
       if (!spec || Z_TYPE_P(spec) != IS_ARRAY) {
         throw_tprotocolexception("Attempt to send non-Thrift object as a T_STRUCT", INVALID_DATA);
       }
@@ -893,7 +900,13 @@
 void validate_thrift_object(zval* object) {
     zend_class_entry* object_class_entry = Z_OBJCE_P(object);
     zval* is_validate = zend_read_static_property(object_class_entry, "isValidate", sizeof("isValidate")-1, true);
+    if (is_validate) {
+      ZVAL_DEREF(is_validate);
+    }
     zval* spec = zend_read_static_property(object_class_entry, "_TSPEC", sizeof("_TSPEC")-1, true);
+    if (spec) {
+      ZVAL_DEREF(spec);
+    }
     HashPosition key_ptr;
     zval* val_ptr;
 
@@ -1027,6 +1040,9 @@
 
   try {
     zval* spec = zend_read_static_property(Z_OBJCE_P(request_struct), "_TSPEC", sizeof("_TSPEC")-1, true);
+    if (spec) {
+      ZVAL_DEREF(spec);
+    }
 
     if (!spec || Z_TYPE_P(spec) != IS_ARRAY) {
       throw_tprotocolexception("Attempt serialize from non-Thrift object", INVALID_DATA);
@@ -1091,6 +1107,7 @@
       zval ex;
       createObject("\\Thrift\\Exception\\TApplicationException", &ex);
       zval* spec = zend_read_static_property(Z_OBJCE(ex), "_TSPEC", sizeof("_TPSEC")-1, false);
+      ZVAL_DEREF(spec);
       if (EG(exception)) {
         zend_object *ex = EG(exception);
         EG(exception) = nullptr;
@@ -1102,6 +1119,9 @@
 
     createObject(ZSTR_VAL(obj_typename), return_value);
     zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, true);
+    if (spec) {
+      ZVAL_DEREF(spec);
+    }
     if (!spec || Z_TYPE_P(spec) != IS_ARRAY) {
       throw_tprotocolexception("Attempt deserialize to non-Thrift object", INVALID_DATA);
     }
@@ -1135,6 +1155,7 @@
 
     createObject(ZSTR_VAL(obj_typename), return_value);
     zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false);
+    ZVAL_DEREF(spec);
     binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec));
   } catch (const PHPExceptionWrapper& ex) {
     // ex will be destructed, so copy to a zval that zend_throw_exception_object can take ownership of
diff --git a/lib/php/test/Fixtures.php b/lib/php/test/Fixtures.php
new file mode 100644
index 0000000..fd57d83
--- /dev/null
+++ b/lib/php/test/Fixtures.php
@@ -0,0 +1,194 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace Test\Thrift;
+
+use ThriftTest\Xtruct;
+use ThriftTest\Xtruct2;
+use ThriftTest\Numberz;
+use ThriftTest\Insanity;
+
+class Fixtures
+{
+    public static $bufsize = 8192; //big enough to read biggest serialized Fixture arg.
+    public static $testArgs = array();
+
+    public static function populateTestArgs()
+    {
+        self::$testArgs['testString1'] = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
+
+        self::$testArgs['testString2'] =
+            "quote: \\\" backslash:" .
+            " forwardslash-escaped: \\/ " .
+            " backspace: \b formfeed: \f newline: \n return: \r tab: " .
+            " now-all-of-them-together: \"\\\/\b\n\r\t" .
+            " now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><";
+
+        self::$testArgs['testString3'] =
+            "string that ends in double-backslash \\\\";
+
+        self::$testArgs['testUnicodeStringWithNonBMP'] =
+            "สวัสดี/𝒯";
+
+        self::$testArgs['testDouble'] = 3.1415926535898;
+
+        // TODO: add testBinary() call
+
+        self::$testArgs['testByte'] = 0x01;
+
+        self::$testArgs['testI32'] = pow(2, 30);
+
+        if (PHP_INT_SIZE == 8) {
+            self::$testArgs['testI64'] = pow(2, 60);
+        } else {
+            self::$testArgs['testI64'] = "1152921504606847000";
+        }
+
+        self::$testArgs['testStruct'] =
+            new Xtruct(
+                array(
+                    'string_thing' => 'worked',
+                    'byte_thing' => 0x01,
+                    'i32_thing' => pow(2, 30),
+                    'i64_thing' => self::$testArgs['testI64']
+                )
+            );
+
+        self::$testArgs['testNestNested'] =
+            new Xtruct(
+                array(
+                    'string_thing' => 'worked',
+                    'byte_thing' => 0x01,
+                    'i32_thing' => pow(2, 30),
+                    'i64_thing' => self::$testArgs['testI64']
+                )
+            );
+
+        self::$testArgs['testNest'] =
+            new Xtruct2(
+                array(
+                    'byte_thing' => 0x01,
+                    'struct_thing' => self::$testArgs['testNestNested'],
+                    'i32_thing' => pow(2, 15)
+                )
+            );
+
+        self::$testArgs['testMap'] =
+            array(
+                7 => 77,
+                8 => 88,
+                9 => 99
+            );
+
+        self::$testArgs['testStringMap'] =
+            array(
+                "a" => "123",
+                "a b" => "with spaces ",
+                "same" => "same",
+                "0" => "numeric key",
+                "longValue" => self::$testArgs['testString1'],
+                self::$testArgs['testString1'] => "long key"
+            );
+
+        self::$testArgs['testSet'] = array(1 => true, 5 => true, 6 => true);
+
+        self::$testArgs['testList'] = array(1, 2, 3);
+
+        self::$testArgs['testEnum'] = Numberz::ONE;
+
+        self::$testArgs['testTypedef'] = 69;
+
+        self::$testArgs['testMapMapExpectedResult'] =
+            array(
+                4 => array(
+                    1 => 1,
+                    2 => 2,
+                    3 => 3,
+                    4 => 4,
+                ),
+                -4 => array(
+                    -4 => -4,
+                    -3 => -3,
+                    -2 => -2,
+                    -1 => -1
+                )
+            );
+
+        // testInsanity ... takes a few steps to set up!
+
+        $xtruct1 =
+            new Xtruct(
+                array(
+                    'string_thing' => 'Goodbye4',
+                    'byte_thing' => 4,
+                    'i32_thing' => 4,
+                    'i64_thing' => 4
+                )
+            );
+
+        $xtruct2 =
+            new Xtruct(
+                array(
+                    'string_thing' => 'Hello2',
+                    'byte_thing' => 2,
+                    'i32_thing' => 2,
+                    'i64_thing' => 2
+                )
+            );
+
+        $userMap =
+            array(
+                Numberz::FIVE => 5,
+                Numberz::EIGHT => 8
+            );
+
+        $insanity2 =
+            new Insanity(
+                array(
+                    'userMap' => $userMap,
+                    'xtructs' => array($xtruct1, $xtruct2)
+                )
+            );
+
+        $insanity3 = $insanity2;
+
+        $insanity6 =
+            new Insanity(
+                array(
+                    'userMap' => null,
+                    'xtructs' => null
+                )
+            );
+
+        self::$testArgs['testInsanityExpectedResult'] =
+            array(
+                "1" => array(
+                    Numberz::TWO => $insanity2,
+                    Numberz::THREE => $insanity3
+                ),
+                "2" => array(
+                    Numberz::SIX => $insanity6
+                )
+            );
+    }
+}
diff --git a/lib/php/test/JsonSerialize/JsonSerializeTest.php b/lib/php/test/JsonSerialize/JsonSerializeTest.php
new file mode 100644
index 0000000..c668652
--- /dev/null
+++ b/lib/php/test/JsonSerialize/JsonSerializeTest.php
@@ -0,0 +1,116 @@
+<?php
+/*
+ * 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.
+ */
+
+namespace Test\Thrift\JsonSerialize;
+
+use PHPUnit\Framework\TestCase;
+use stdClass;
+
+require __DIR__ . '/../../../../vendor/autoload.php';
+
+/**
+ * @runTestsInSeparateProcesses
+ */
+class JsonSerializeTest extends TestCase
+{
+    protected function setUp()
+    {
+        if (version_compare(phpversion(), '5.4', '<')) {
+            $this->markTestSkipped('Requires PHP 5.4 or newer!');
+        }
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpjs');
+    }
+
+    public function testEmptyStruct()
+    {
+        $empty = new \ThriftTest\EmptyStruct(array('non_existing_key' => 'bar'));
+        $this->assertEquals(new stdClass(), json_decode(json_encode($empty)));
+    }
+
+    public function testStringsAndInts()
+    {
+        $input = array(
+            'string_thing' => 'foo',
+            'i64_thing' => 1234567890,
+        );
+        $xtruct = new \ThriftTest\Xtruct($input);
+
+        // Xtruct's 'i32_thing' and 'byte_thing' fields should not be present here!
+        $expected = new stdClass();
+        $expected->string_thing = $input['string_thing'];
+        $expected->i64_thing = $input['i64_thing'];
+        $this->assertEquals($expected, json_decode(json_encode($xtruct)));
+    }
+
+    public function testNestedStructs()
+    {
+        $xtruct2 = new \ThriftTest\Xtruct2(array(
+            'byte_thing' => 42,
+            'struct_thing' => new \ThriftTest\Xtruct(array(
+                'i32_thing' => 123456,
+            )),
+        ));
+
+        $expected = new stdClass();
+        $expected->byte_thing = $xtruct2->byte_thing;
+        $expected->struct_thing = new stdClass();
+        $expected->struct_thing->i32_thing = $xtruct2->struct_thing->i32_thing;
+        $this->assertEquals($expected, json_decode(json_encode($xtruct2)));
+    }
+
+    public function testInsanity()
+    {
+        $xinput = array('string_thing' => 'foo');
+        $xtruct = new \ThriftTest\Xtruct($xinput);
+        $insanity = new \ThriftTest\Insanity(array(
+            'xtructs' => array($xtruct, $xtruct, $xtruct)
+        ));
+        $expected = new stdClass();
+        $expected->xtructs = array((object)$xinput, (object)$xinput, (object)$xinput);
+        $this->assertEquals($expected, json_decode(json_encode($insanity)));
+    }
+
+    public function testNestedLists()
+    {
+        $bonk = new \ThriftTest\Bonk(array('message' => 'foo'));
+        $nested = new \ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk)))));
+        $expected = new stdClass();
+        $expected->bonk = array(array(array((object)array('message' => 'foo'))));
+        $this->assertEquals($expected, json_decode(json_encode($nested)));
+    }
+
+    public function testMaps()
+    {
+        $intmap = new \ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]);
+        $emptymap = new \ThriftTest\ThriftTest_testMap_args([]);
+        $this->assertEquals('{"thing":{"0":"zero"}}', json_encode($intmap));
+        $this->assertEquals('{}', json_encode($emptymap));
+    }
+
+    public function testScalarTypes()
+    {
+        $b = new \ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']);
+        $this->assertEquals('{"im_true":true,"im_false":false}', json_encode($b));
+        $s = new \ThriftTest\StructA(['s' => 42]);
+        $this->assertEquals('{"s":"42"}', json_encode($s));
+    }
+}
diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am
index c872b1a..4824688 100755
--- a/lib/php/test/Makefile.am
+++ b/lib/php/test/Makefile.am
@@ -17,9 +17,11 @@
 # under the License.
 #
 
+PHPUNIT=php $(top_srcdir)/vendor/bin/phpunit
+
 stubs: ../../../test/ThriftTest.thrift  TestValidators.thrift
-	mkdir -p ./packages
-	$(THRIFT) --gen php -r --out ./packages ../../../test/ThriftTest.thrift
+	mkdir -p ./packages/php
+	$(THRIFT) --gen php -r --out ./packages/php ../../../test/ThriftTest.thrift
 	mkdir -p ./packages/phpv
 	mkdir -p ./packages/phpvo
 	mkdir -p ./packages/phpjs
@@ -27,23 +29,21 @@
 	$(THRIFT) --gen php:validate,oop -r --out ./packages/phpvo  TestValidators.thrift
 	$(THRIFT) --gen php:json         -r --out ./packages/phpjs  TestValidators.thrift
 
-check-json-serializer: stubs
-if HAVE_PHPUNIT
-	$(PHPUNIT) --log-junit=TEST-json-serializer.xml Test/Thrift/JsonSerialize/
-endif
+deps: $(top_srcdir)/composer.json
+	composer install --working-dir=$(top_srcdir)
 
-check-validator: stubs
-	php Test/Thrift/TestValidators.php
-	php Test/Thrift/TestValidators.php -oop
+all-local: deps
 
-check-protocol:	stubs
-if HAVE_PHPUNIT
-	$(PHPUNIT) --log-junit=TEST-log-json-protocol.xml Test/Thrift/Protocol/TestTJSONProtocol.php
-	$(PHPUNIT) --log-junit=TEST-binary-serializer.xml Test/Thrift/Protocol/TestBinarySerializer.php
-	$(PHPUNIT) --log-junit=TEST-log-simple-json-protocol.xml Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
-endif
+check-json-serializer: deps stubs
+	$(PHPUNIT) --log-junit=TEST-log-json-serializer.xml JsonSerialize/
 
-check: stubs \
+check-validator: deps stubs
+	$(PHPUNIT) --log-junit=TEST-log-validator.xml Validator/
+
+check-protocol:	deps stubs
+	$(PHPUNIT) --log-junit=TEST-log-protocol.xml Protocol/
+
+check: deps stubs \
   check-protocol \
   check-validator \
   check-json-serializer
@@ -51,9 +51,3 @@
 clean-local:
 	$(RM) -r ./packages
 	$(RM) TEST-*.xml
-
-EXTRA_DIST = \
-	Test \
-	TestValidators.thrift
-
-
diff --git a/lib/php/test/Protocol/BinarySerializerTest.php b/lib/php/test/Protocol/BinarySerializerTest.php
new file mode 100644
index 0000000..71b0bb5
--- /dev/null
+++ b/lib/php/test/Protocol/BinarySerializerTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace Test\Thrift\Protocol;
+
+use PHPUnit\Framework\TestCase;
+use Thrift\Serializer\TBinarySerializer;
+
+require __DIR__ . '/../../../../vendor/autoload.php';
+
+/***
+ * This test suite depends on running the compiler against the
+ * standard ThriftTest.thrift file:
+ *
+ * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
+ *   --out ./packages ../../../test/ThriftTest.thrift
+ *
+ * @runTestsInSeparateProcesses
+ */
+class BinarySerializerTest extends TestCase
+{
+    public function setUp()
+    {
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
+    }
+
+    /**
+     * We try to serialize and deserialize a random object to make sure no exceptions are thrown.
+     * @see THRIFT-1579
+     */
+    public function testBinarySerializer()
+    {
+        $struct = new \ThriftTest\Xtruct(array('string_thing' => 'abc'));
+        $serialized = TBinarySerializer::serialize($struct, 'ThriftTest\\Xtruct');
+        $deserialized = TBinarySerializer::deserialize($serialized, 'ThriftTest\\Xtruct');
+        $this->assertEquals($struct, $deserialized);
+    }
+}
diff --git a/lib/php/test/Protocol/TJSONProtocolFixtures.php b/lib/php/test/Protocol/TJSONProtocolFixtures.php
new file mode 100644
index 0000000..dd9039f
--- /dev/null
+++ b/lib/php/test/Protocol/TJSONProtocolFixtures.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace Test\Thrift\Protocol;
+
+class TJSONProtocolFixtures
+{
+    public static $testArgsJSON = array();
+
+    public static function populateTestArgsJSON()
+    {
+        self::$testArgsJSON['testVoid'] = '{}';
+
+        self::$testArgsJSON['testString1'] = '{"1":{"str":"Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ \/ ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe\'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски \/ Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча\/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"}}';
+
+        self::$testArgsJSON['testString2'] = '{"1":{"str":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/  backspace: \\\\b formfeed: \f newline: \n return: \r tab:  now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}}';
+
+        self::$testArgsJSON['testString3'] = '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}';
+
+        self::$testArgsJSON['testUnicodeStringWithNonBMP'] = '{"1":{"str":"สวัสดี\/𝒯"}}';
+
+        self::$testArgsJSON['testDouble'] = '{"1":{"dbl":3.1415926535898}}';
+
+        self::$testArgsJSON['testByte'] = '{"1":{"i8":1}}';
+
+        self::$testArgsJSON['testI32'] = '{"1":{"i32":1073741824}}';
+
+        if (PHP_INT_SIZE == 8) {
+            self::$testArgsJSON['testI64'] = '{"1":{"i64":' . pow(2, 60) . '}}';
+            self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}}}';
+            self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}},"3":{"i32":32768}}}}';
+        } else {
+            self::$testArgsJSON['testI64'] = '{"1":{"i64":1152921504606847000}}';
+            self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}';
+            self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}';
+        }
+
+        self::$testArgsJSON['testMap'] = '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}';
+
+        self::$testArgsJSON['testStringMap'] = '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}]}}';
+
+        self::$testArgsJSON['testSet'] = '{"1":{"set":["i32",3,1,5,6]}}';
+
+        self::$testArgsJSON['testList'] = '{"1":{"lst":["i32",3,1,2,3]}}';
+
+        self::$testArgsJSON['testEnum'] = '{"1":{"i32":1}}';
+
+        self::$testArgsJSON['testTypedef'] = '{"1":{"i64":69}}';
+
+        self::$testArgsJSON['testMapMap'] = '{"0":{"map":["i32","map",2,{"4":["i32","i32",4,{"1":1,"2":2,"3":3,"4":4}],"-4":["i32","i32",4,{"-4":-4,"-3":-3,"-2":-2,"-1":-1}]}]}}';
+
+        self::$testArgsJSON['testInsanity'] = '{"0":{"map":["i64","map",2,{"1":["i32","rec",2,{"2":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}},"3":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}}}],"2":["i32","rec",1,{"6":{}}]}]}}';
+    }
+}
diff --git a/lib/php/test/Protocol/TJSONProtocolTest.php b/lib/php/test/Protocol/TJSONProtocolTest.php
new file mode 100644
index 0000000..bf0ecce
--- /dev/null
+++ b/lib/php/test/Protocol/TJSONProtocolTest.php
@@ -0,0 +1,518 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace Test\Thrift\Protocol;
+
+use PHPUnit\Framework\TestCase;
+use Test\Thrift\Fixtures;
+use Thrift\Protocol\TJSONProtocol;
+use Thrift\Transport\TMemoryBuffer;
+
+require __DIR__ . '/../../../../vendor/autoload.php';
+
+/***
+ * This test suite depends on running the compiler against the
+ * standard ThriftTest.thrift file:
+ *
+ * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
+ *   --out ./packages ../../../test/ThriftTest.thrift
+ *
+ * @runTestsInSeparateProcesses
+ */
+class TJSONProtocolTest extends TestCase
+{
+    private $transport;
+    private $protocol;
+
+    public static function setUpBeforeClass()
+    {
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
+
+        Fixtures::populateTestArgs();
+        TJSONProtocolFixtures::populateTestArgsJSON();
+    }
+
+    public function setUp()
+    {
+        $this->transport = new TMemoryBuffer();
+        $this->protocol = new TJSONProtocol($this->transport);
+        $this->transport->open();
+    }
+
+    /**
+     * WRITE TESTS
+     */
+    public function testVoidWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testVoid_args();
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testVoid'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString1Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testString1'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testString1'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString2Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testString2'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testString2'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testDoubleWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testDouble_args();
+        $args->thing = Fixtures::$testArgs['testDouble'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testDouble'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testByteWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testByte_args();
+        $args->thing = Fixtures::$testArgs['testByte'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testByte'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI32Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testI32_args();
+        $args->thing = Fixtures::$testArgs['testI32'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testI32'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI64Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testI64_args();
+        $args->thing = Fixtures::$testArgs['testI64'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testI64'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStructWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testStruct_args();
+        $args->thing = Fixtures::$testArgs['testStruct'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testStruct'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testNestWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testNest_args();
+        $args->thing = Fixtures::$testArgs['testNest'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testNest'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testMapWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testMap_args();
+        $args->thing = Fixtures::$testArgs['testMap'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testMap'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStringMapWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testStringMap_args();
+        $args->thing = Fixtures::$testArgs['testStringMap'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testStringMap'];
+
+        /*
+         * The $actual returns unescaped string.
+         * It is required to to decode then encode it again
+         * to get the expected escaped unicode.
+         */
+        $this->assertEquals($expected, json_encode(json_decode($actual)));
+    }
+
+    public function testSetWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testSet_args();
+        $args->thing = Fixtures::$testArgs['testSet'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testSet'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testListWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testList_args();
+        $args->thing = Fixtures::$testArgs['testList'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testList'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testEnumWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testEnum_args();
+        $args->thing = Fixtures::$testArgs['testEnum'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testEnum'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testTypedefWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testTypedef_args();
+        $args->thing = Fixtures::$testArgs['testTypedef'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testTypedef'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    /**
+     * READ TESTS
+     */
+    public function testVoidRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testVoid']
+        );
+        $args = new \ThriftTest\ThriftTest_testVoid_args();
+        $args->read($this->protocol);
+    }
+
+    public function testString1Read()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testString1']
+        );
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testString1'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString2Read()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testString2']
+        );
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testString2'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString3Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testString3'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testString3'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString4Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testUnicodeStringWithNonBMP'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TJSONProtocolFixtures::$testArgsJSON['testUnicodeStringWithNonBMP'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testDoubleRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testDouble']
+        );
+        $args = new \ThriftTest\ThriftTest_testDouble_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testDouble'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testByteRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testByte']
+        );
+        $args = new \ThriftTest\ThriftTest_testByte_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testByte'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI32Read()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testI32']
+        );
+        $args = new \ThriftTest\ThriftTest_testI32_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testI32'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI64Read()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testI64']
+        );
+        $args = new \ThriftTest\ThriftTest_testI64_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testI64'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStructRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testStruct']
+        );
+        $args = new \ThriftTest\ThriftTest_testStruct_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testStruct'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testNestRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testNest']
+        );
+        $args = new \ThriftTest\ThriftTest_testNest_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testNest'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testMapRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testMap']
+        );
+        $args = new \ThriftTest\ThriftTest_testMap_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testMap'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStringMapRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testStringMap']
+        );
+        $args = new \ThriftTest\ThriftTest_testStringMap_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testStringMap'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testSetRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testSet']
+        );
+        $args = new \ThriftTest\ThriftTest_testSet_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testSet'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testListRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testList']
+        );
+        $args = new \ThriftTest\ThriftTest_testList_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testList'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testEnumRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testEnum']
+        );
+        $args = new \ThriftTest\ThriftTest_testEnum_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testEnum'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testTypedefRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testTypedef']
+        );
+        $args = new \ThriftTest\ThriftTest_testTypedef_args();
+        $args->read($this->protocol);
+
+        $actual = $args->thing;
+        $expected = Fixtures::$testArgs['testTypedef'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testMapMapRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testMapMap']
+        );
+        $result = new \ThriftTest\ThriftTest_testMapMap_result();
+        $result->read($this->protocol);
+
+        $actual = $result->success;
+        $expected = Fixtures::$testArgs['testMapMapExpectedResult'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testInsanityRead()
+    {
+        $this->transport->write(
+            TJSONProtocolFixtures::$testArgsJSON['testInsanity']
+        );
+        $result = new \ThriftTest\ThriftTest_testInsanity_result();
+        $result->read($this->protocol);
+
+        $actual = $result->success;
+        $expected = Fixtures::$testArgs['testInsanityExpectedResult'];
+
+        $this->assertEquals($expected, $actual);
+    }
+}
diff --git a/lib/php/test/Protocol/TSimpleJSONProtocolFixtures.php b/lib/php/test/Protocol/TSimpleJSONProtocolFixtures.php
new file mode 100644
index 0000000..547fd86
--- /dev/null
+++ b/lib/php/test/Protocol/TSimpleJSONProtocolFixtures.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace test\Thrift\Protocol;
+
+class TSimpleJSONProtocolFixtures
+{
+    public static $testArgsJSON = array();
+
+    public static function populateTestArgsSimpleJSON()
+    {
+        self::$testArgsJSON['testVoid'] = '{}';
+
+        self::$testArgsJSON['testString1'] = '{"thing":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e"}';
+
+        self::$testArgsJSON['testString2'] = '{"thing":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/  backspace: \\\\b formfeed: \f newline: \n return: \r tab:  now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}';
+
+        self::$testArgsJSON['testDouble'] = '{"thing":3.1415926535898}';
+
+        self::$testArgsJSON['testByte'] = '{"thing":1}';
+
+        self::$testArgsJSON['testI32'] = '{"thing":1073741824}';
+
+        if (PHP_INT_SIZE == 8) {
+            self::$testArgsJSON['testI64'] = '{"thing":' . pow(2, 60) . '}';
+            self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '}}';
+            self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '},"i32_thing":32768}}';
+        } else {
+            self::$testArgsJSON['testI64'] = '{"thing":1152921504606847000}';
+
+            self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000}}';
+            self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000},"i32_thing":32768}}';
+        }
+
+        self::$testArgsJSON['testMap'] = '{"thing":{"7":77,"8":88,"9":99}}';
+
+        self::$testArgsJSON['testStringMap'] = '{"thing":{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}}';
+
+        self::$testArgsJSON['testSet'] = '{"thing":[1,5,6]}';
+
+        self::$testArgsJSON['testList'] = '{"thing":[1,2,3]}';
+
+        self::$testArgsJSON['testEnum'] = '{"thing":1}';
+
+        self::$testArgsJSON['testTypedef'] = '{"thing":69}';
+    }
+}
diff --git a/lib/php/test/Protocol/TSimpleJSONProtocolTest.php b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php
new file mode 100644
index 0000000..e4a1373
--- /dev/null
+++ b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php
@@ -0,0 +1,254 @@
+<?php
+
+/*
+ * 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.
+ *
+ * @package thrift.test
+ */
+
+namespace Test\Thrift\Protocol;
+
+use PHPUnit\Framework\TestCase;
+use Test\Thrift\Fixtures;
+use Thrift\Protocol\TSimpleJSONProtocol;
+use Thrift\Transport\TMemoryBuffer;
+
+require __DIR__ . '/../../../../vendor/autoload.php';
+
+/***
+ * This test suite depends on running the compiler against the
+ * standard ThriftTest.thrift file:
+ *
+ * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
+ *   --out ./packages ../../../test/ThriftTest.thrift
+ *
+ * @runTestsInSeparateProcesses
+ */
+class TSimpleJSONProtocolTest extends TestCase
+{
+    private $transport;
+    private $protocol;
+
+    public static function setUpBeforeClass()
+    {
+
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
+
+        Fixtures::populateTestArgs();
+        TSimpleJSONProtocolFixtures::populateTestArgsSimpleJSON();
+    }
+
+    public function setUp()
+    {
+        $this->transport = new TMemoryBuffer();
+        $this->protocol = new TSimpleJSONProtocol($this->transport);
+        $this->transport->open();
+    }
+
+    /**
+     * WRITE TESTS
+     */
+    public function testVoidWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testVoid_args();
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testVoid'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString1Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testString1'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString1'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testString2Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testString_args();
+        $args->thing = Fixtures::$testArgs['testString2'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString2'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testDoubleWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testDouble_args();
+        $args->thing = Fixtures::$testArgs['testDouble'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testDouble'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testByteWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testByte_args();
+        $args->thing = Fixtures::$testArgs['testByte'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testByte'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI32Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testI32_args();
+        $args->thing = Fixtures::$testArgs['testI32'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI32'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testI64Write()
+    {
+        $args = new \ThriftTest\ThriftTest_testI64_args();
+        $args->thing = Fixtures::$testArgs['testI64'];
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI64'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStructWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testStruct_args();
+        $args->thing = Fixtures::$testArgs['testStruct'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStruct'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testNestWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testNest_args();
+        $args->thing = Fixtures::$testArgs['testNest'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testNest'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testMapWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testMap_args();
+        $args->thing = Fixtures::$testArgs['testMap'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testMap'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testStringMapWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testStringMap_args();
+        $args->thing = Fixtures::$testArgs['testStringMap'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStringMap'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testSetWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testSet_args();
+        $args->thing = Fixtures::$testArgs['testSet'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testSet'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testListWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testList_args();
+        $args->thing = Fixtures::$testArgs['testList'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testList'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testEnumWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testEnum_args();
+        $args->thing = Fixtures::$testArgs['testEnum'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testEnum'];
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testTypedefWrite()
+    {
+        $args = new \ThriftTest\ThriftTest_testTypedef_args();
+        $args->thing = Fixtures::$testArgs['testTypedef'];
+
+        $args->write($this->protocol);
+
+        $actual = $this->transport->read(Fixtures::$bufsize);
+        $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testTypedef'];
+
+        $this->assertEquals($expected, $actual);
+    }
+}
diff --git a/lib/php/test/Test/Thrift/Fixtures.php b/lib/php/test/Test/Thrift/Fixtures.php
deleted file mode 100644
index 2c60a08..0000000
--- a/lib/php/test/Test/Thrift/Fixtures.php
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-
-/*
- * 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.
- *
- * @package thrift.test
- */
-
-namespace Test\Thrift;
-
-use ThriftTest\Xtruct;
-use ThriftTest\Xtruct2;
-use ThriftTest\Numberz;
-use ThriftTest\Insanity;
-
-class Fixtures
-{
-  public static $testArgs = array();
-
-  public static function populateTestArgs()
-  {
-    self::$testArgs['testString1'] = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
-
-    self::$testArgs['testString2'] =
-      "quote: \\\" backslash:" .
-      " forwardslash-escaped: \\/ " .
-      " backspace: \b formfeed: \f newline: \n return: \r tab: " .
-      " now-all-of-them-together: \"\\\/\b\n\r\t" .
-      " now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><";
-
-    self::$testArgs['testString3'] =
-      "string that ends in double-backslash \\\\";
-
-    self::$testArgs['testUnicodeStringWithNonBMP'] =
-      "สวัสดี/𝒯";
-
-    self::$testArgs['testDouble'] = 3.1415926535898;
-
-	// TODO: add testBinary() call
-	
-    self::$testArgs['testByte'] = 0x01;
-
-    self::$testArgs['testI32'] = pow( 2, 30 );
-
-    if (PHP_INT_SIZE == 8) {
-      self::$testArgs['testI64'] = pow( 2, 60 );
-    } else {
-      self::$testArgs['testI64'] = "1152921504606847000";
-    }
-
-    self::$testArgs['testStruct'] =
-      new Xtruct(
-            array(
-                    'string_thing' => 'worked',
-                    'byte_thing' => 0x01,
-                    'i32_thing' => pow( 2, 30 ),
-                    'i64_thing' => self::$testArgs['testI64']
-                    )
-            );
-
-    self::$testArgs['testNestNested'] =
-      new Xtruct(
-            array(
-                    'string_thing' => 'worked',
-                    'byte_thing' => 0x01,
-                    'i32_thing' => pow( 2, 30 ),
-                    'i64_thing' => self::$testArgs['testI64']
-                    )
-            );
-
-    self::$testArgs['testNest'] =
-      new Xtruct2(
-            array(
-                'byte_thing' => 0x01,
-                'struct_thing' => self::$testArgs['testNestNested'],
-                'i32_thing' => pow( 2, 15 )
-                )
-            );
-
-    self::$testArgs['testMap'] =
-      array(
-            7 => 77,
-            8 => 88,
-            9 => 99
-            );
-
-    self::$testArgs['testStringMap'] =
-      array(
-            "a" => "123",
-            "a b" => "with spaces ",
-            "same" => "same",
-            "0" => "numeric key",
-            "longValue" => self::$testArgs['testString1'],
-            self::$testArgs['testString1'] => "long key"
-            );
-
-    self::$testArgs['testSet'] = array( 1 => true, 5 => true, 6 => true );
-
-    self::$testArgs['testList'] = array( 1, 2, 3 );
-
-    self::$testArgs['testEnum'] = Numberz::ONE;
-
-    self::$testArgs['testTypedef'] = 69;
-
-    self::$testArgs['testMapMapExpectedResult'] =
-      array(
-            4 => array(
-                       1 => 1,
-                       2 => 2,
-                       3 => 3,
-                       4 => 4,
-                       ),
-            -4 => array(
-                        -4 => -4,
-                        -3 => -3,
-                        -2 => -2,
-                        -1 => -1
-                        )
-            );
-
-    // testInsanity ... takes a few steps to set up!
-
-    $xtruct1 =
-      new Xtruct(
-            array(
-                'string_thing' => 'Goodbye4',
-                'byte_thing' => 4,
-                'i32_thing' => 4,
-                'i64_thing' => 4
-                )
-            );
-
-    $xtruct2 =
-      new Xtruct(
-            array(
-                'string_thing' => 'Hello2',
-                'byte_thing' =>2,
-                'i32_thing' => 2,
-                'i64_thing' => 2
-                )
-            );
-
-    $userMap =
-      array(
-            Numberz::FIVE => 5,
-            Numberz::EIGHT => 8
-            );
-
-    $insanity2 =
-      new Insanity(
-            array(
-                'userMap' => $userMap,
-                'xtructs' => array($xtruct1,$xtruct2)
-                )
-            );
-
-    $insanity3 = $insanity2;
-
-    $insanity6 =
-      new Insanity(
-            array(
-                'userMap' => null,
-                'xtructs' => null
-                )
-            );
-
-    self::$testArgs['testInsanityExpectedResult'] =
-      array(
-            "1" => array(
-                         Numberz::TWO => $insanity2,
-                         Numberz::THREE => $insanity3
-                    ),
-            "2" => array(
-                         Numberz::SIX => $insanity6
-                    )
-            );
-
-  }
-}
diff --git a/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php b/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php
deleted file mode 100644
index 2471b52..0000000
--- a/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-/*
- * 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.
- */
-
-namespace Test\Thrift\JsonSerialize;
-
-use stdClass;
-use Thrift\ClassLoader\ThriftClassLoader;
-
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
-
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
-$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages/phpjs');
-$loader->register();
-
-class JsonSerializeTest extends \PHPUnit_Framework_TestCase
-{
-  protected function setUp() {
-    if (version_compare(phpversion(), '5.4', '<')) {
-      $this->markTestSkipped('Requires PHP 5.4 or newer!');
-    }
-  }
-
-  public function testEmptyStruct()
-  {
-    $empty = new \ThriftTest\EmptyStruct(array('non_existing_key' => 'bar'));
-    $this->assertEquals(new stdClass(), json_decode(json_encode($empty)));
-  }
-
-  public function testStringsAndInts()
-  {
-    $input = array(
-      'string_thing' => 'foo',
-      'i64_thing' => 1234567890,
-    );
-    $xtruct = new \ThriftTest\Xtruct($input);
-
-    // Xtruct's 'i32_thing' and 'byte_thing' fields should not be present here!
-    $expected = new stdClass();
-    $expected->string_thing = $input['string_thing'];
-    $expected->i64_thing = $input['i64_thing'];
-    $this->assertEquals($expected, json_decode(json_encode($xtruct)));
-  }
-
-  public function testNestedStructs()
-  {
-    $xtruct2 = new \ThriftTest\Xtruct2(array(
-      'byte_thing' => 42,
-      'struct_thing' => new \ThriftTest\Xtruct(array(
-        'i32_thing' => 123456,
-      )),
-    ));
-
-    $expected = new stdClass();
-    $expected->byte_thing = $xtruct2->byte_thing;
-    $expected->struct_thing = new stdClass();
-    $expected->struct_thing->i32_thing = $xtruct2->struct_thing->i32_thing;
-    $this->assertEquals($expected, json_decode(json_encode($xtruct2)));
-  }
-
-  public function testInsanity()
-  {
-    $xinput = array('string_thing' => 'foo');
-    $xtruct = new \ThriftTest\Xtruct($xinput);
-    $insanity = new \ThriftTest\Insanity(array(
-      'xtructs' => array($xtruct, $xtruct, $xtruct)
-    ));
-    $expected = new stdClass();
-    $expected->xtructs = array((object) $xinput, (object) $xinput, (object) $xinput);
-    $this->assertEquals($expected, json_decode(json_encode($insanity)));
-  }
-
-  public function testNestedLists()
-  {
-    $bonk = new \ThriftTest\Bonk(array('message' => 'foo'));
-    $nested = new \ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk)))));
-    $expected = new stdClass();
-    $expected->bonk = array(array(array((object) array('message' => 'foo'))));
-    $this->assertEquals($expected, json_decode(json_encode($nested)));
-  }
-
-  public function testMaps()
-  {
-    $intmap = new \ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]);
-    $emptymap = new \ThriftTest\ThriftTest_testMap_args([]);
-    $this->assertEquals('{"thing":{"0":"zero"}}', json_encode($intmap));
-    $this->assertEquals('{}', json_encode($emptymap));
-  }
-
-  public function testScalarTypes()
-  {
-    $b = new \ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']);
-    $this->assertEquals('{"im_true":true,"im_false":false}', json_encode($b));
-    $s = new \ThriftTest\StructA(['s' => 42]);
-    $this->assertEquals('{"s":"42"}', json_encode($s));
-  }
-
-}
diff --git a/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php b/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php
deleted file mode 100644
index a983216..0000000
--- a/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-/*
- * 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.
- *
- * @package thrift.test
- */
-
-namespace Test\Thrift\Protocol;
-
-use Thrift\ClassLoader\ThriftClassLoader;
-use Thrift\Serializer\TBinarySerializer;
-
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
-
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
-$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
-$loader->register();
-
-/***
- * This test suite depends on running the compiler against the
- * standard ThriftTest.thrift file:
- *
- * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
- *   --out ./packages ../../../test/ThriftTest.thrift
- */
-
-class TestBinarySerializer extends \PHPUnit_Framework_TestCase
-{
-
-  public function setUp()
-  {
-  }
-
-  /**
-    * We try to serialize and deserialize a random object to make sure no exceptions are thrown.
-    * @see THRIFT-1579
-    */
-  public function testBinarySerializer()
-  {
-    $struct = new \ThriftTest\Xtruct(array('string_thing' => 'abc'));
-    $serialized = TBinarySerializer::serialize($struct, 'ThriftTest\\Xtruct');
-    $deserialized = TBinarySerializer::deserialize($serialized, 'ThriftTest\\Xtruct');
-    $this->assertEquals($struct, $deserialized);
-  }
-
-}
diff --git a/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php b/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php
deleted file mode 100755
index a4ca9d5..0000000
--- a/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php
+++ /dev/null
@@ -1,583 +0,0 @@
-<?php
-
-/*
- * 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.
- *
- * @package thrift.test
- */
-
-namespace test\Thrift\Protocol;
-
-use Thrift\ClassLoader\ThriftClassLoader;
-use Test\Thrift\Fixtures;
-use Thrift\Transport\TMemoryBuffer;
-use Thrift\Protocol\TJSONProtocol;
-
-define( 'BUFSIZ', 8192 ); //big enough to read biggest serialized Fixture arg.
-
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
-
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
-$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
-$loader->register();
-
-/***
- * This test suite depends on running the compiler against the
- * standard ThriftTest.thrift file:
- *
- * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
- *   --out ./packages ../../../test/ThriftTest.thrift
- */
-
-class TestTJSONProtocol extends \PHPUnit_Framework_TestCase
-{
-  private $transport;
-  private $protocol;
-
-  public static function setUpBeforeClass()
-  {
-    Fixtures::populateTestArgs();
-    TestTJSONProtocol_Fixtures::populateTestArgsJSON();
-  }
-
-  public function setUp()
-  {
-    $this->transport = new TMemoryBuffer();
-    $this->protocol = new TJSONProtocol($this->transport);
-    $this->transport->open();
-  }
-
-  /***
-   * WRITE TESTS
-   */
-
-  public function testVoid_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testVoid_args();
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testVoid'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testString1_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testString1'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testString1'];
-
-    #$this->assertEquals( $expected, $actual );
-  }
-
-  public function testString2_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testString2'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testString2'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testDouble_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testDouble_args();
-    $args->thing = Fixtures::$testArgs['testDouble'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testDouble'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testByte_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testByte_args();
-    $args->thing = Fixtures::$testArgs['testByte'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testByte'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI32_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testI32_args();
-    $args->thing = Fixtures::$testArgs['testI32'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testI32'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI64_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testI64_args();
-    $args->thing = Fixtures::$testArgs['testI64'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testI64'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testStruct_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testStruct_args();
-    $args->thing = Fixtures::$testArgs['testStruct'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testStruct'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testNest_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testNest_args();
-    $args->thing = Fixtures::$testArgs['testNest'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testNest'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testMap_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testMap_args();
-    $args->thing = Fixtures::$testArgs['testMap'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testMap'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testStringMap_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testStringMap_args();
-    $args->thing = Fixtures::$testArgs['testStringMap'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testStringMap'];
-
-    /*
-     * The $actual returns unescaped string.
-     * It is required to to decode then encode it again
-     * to get the expected escaped unicode.
-     */
-    $this->assertEquals( $expected, json_encode(json_decode($actual)) );
-  }
-
-  public function testSet_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testSet_args();
-    $args->thing = Fixtures::$testArgs['testSet'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testSet'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testList_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testList_args();
-    $args->thing = Fixtures::$testArgs['testList'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testList'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testEnum_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testEnum_args();
-    $args->thing = Fixtures::$testArgs['testEnum'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testEnum'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testTypedef_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testTypedef_args();
-    $args->thing = Fixtures::$testArgs['testTypedef'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testTypedef'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  /***
-   * READ TESTS
-   */
-
-  public function testVoid_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testVoid']
-                );
-    $args = new \ThriftTest\ThriftTest_testVoid_args();
-    $args->read( $this->protocol );
-  }
-
-  public function testString1_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testString1']
-                );
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testString1'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testString2_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testString2']
-                );
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testString2'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testString3_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testString3'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testString3'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testString4_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testUnicodeStringWithNonBMP'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTJSONProtocol_Fixtures::$testArgsJSON['testUnicodeStringWithNonBMP'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testDouble_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testDouble']
-                );
-    $args = new \ThriftTest\ThriftTest_testDouble_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testDouble'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testByte_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testByte']
-                );
-    $args = new \ThriftTest\ThriftTest_testByte_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testByte'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI32_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testI32']
-                );
-    $args = new \ThriftTest\ThriftTest_testI32_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testI32'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI64_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testI64']
-                );
-    $args = new \ThriftTest\ThriftTest_testI64_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testI64'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testStruct_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testStruct']
-                );
-    $args = new \ThriftTest\ThriftTest_testStruct_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testStruct'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testNest_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testNest']
-                );
-    $args = new \ThriftTest\ThriftTest_testNest_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testNest'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testMap_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testMap']
-                );
-    $args = new \ThriftTest\ThriftTest_testMap_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testMap'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testStringMap_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testStringMap']
-                );
-    $args = new \ThriftTest\ThriftTest_testStringMap_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testStringMap'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testSet_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testSet']
-                );
-    $args = new \ThriftTest\ThriftTest_testSet_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testSet'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testList_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testList']
-                );
-    $args = new \ThriftTest\ThriftTest_testList_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testList'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testEnum_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testEnum']
-                );
-    $args = new \ThriftTest\ThriftTest_testEnum_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testEnum'];
-
-    $this->assertEquals( $expected, $actual );
-
-  }
-
-  public function testTypedef_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testTypedef']
-                );
-    $args = new \ThriftTest\ThriftTest_testTypedef_args();
-    $args->read( $this->protocol );
-
-    $actual = $args->thing;
-    $expected = Fixtures::$testArgs['testTypedef'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testMapMap_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testMapMap']
-                );
-    $result = new \ThriftTest\ThriftTest_testMapMap_result();
-    $result->read( $this->protocol );
-
-    $actual = $result->success;
-    $expected = Fixtures::$testArgs['testMapMapExpectedResult'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testInsanity_Read()
-  {
-    $this->transport->write(
-                TestTJSONProtocol_Fixtures::$testArgsJSON['testInsanity']
-                );
-    $result = new \ThriftTest\ThriftTest_testInsanity_result();
-    $result->read( $this->protocol );
-
-    $actual = $result->success;
-    $expected = Fixtures::$testArgs['testInsanityExpectedResult'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-}
-
-class TestTJSONProtocol_Fixtures
-{
-  public static $testArgsJSON = array();
-
-  public static function populateTestArgsJSON()
-  {
-    self::$testArgsJSON['testVoid'] = '{}';
-
-    self::$testArgsJSON['testString1'] = '{"1":{"str":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e"}}';
-
-    self::$testArgsJSON['testString2'] = '{"1":{"str":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/  backspace: \\\\b formfeed: \f newline: \n return: \r tab:  now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}}';
-
-    self::$testArgsJSON['testString3'] = '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}';
-
-    self::$testArgsJSON['testUnicodeStringWithNonBMP'] = '{"1":{"str":"สวัสดี\/𝒯"}}';
-
-    self::$testArgsJSON['testDouble'] = '{"1":{"dbl":3.1415926535898}}';
-
-    self::$testArgsJSON['testByte'] = '{"1":{"i8":1}}';
-
-    self::$testArgsJSON['testI32'] = '{"1":{"i32":1073741824}}';
-
-    if (PHP_INT_SIZE == 8) {
-      self::$testArgsJSON['testI64'] = '{"1":{"i64":'.pow( 2, 60 ).'}}';
-      self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":'.pow( 2, 60 ).'}}}}';
-      self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":'.pow( 2, 60 ).'}}},"3":{"i32":32768}}}}';
-    } else {
-      self::$testArgsJSON['testI64'] = '{"1":{"i64":1152921504606847000}}';
-      self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}';
-      self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}';
-    }
-
-    self::$testArgsJSON['testMap'] = '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}';
-
-    self::$testArgsJSON['testStringMap'] = '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}]}}';
-
-    self::$testArgsJSON['testSet'] = '{"1":{"set":["i32",3,1,5,6]}}';
-
-    self::$testArgsJSON['testList'] = '{"1":{"lst":["i32",3,1,2,3]}}';
-
-    self::$testArgsJSON['testEnum'] = '{"1":{"i32":1}}';
-
-    self::$testArgsJSON['testTypedef'] = '{"1":{"i64":69}}';
-
-    self::$testArgsJSON['testMapMap'] = '{"0":{"map":["i32","map",2,{"4":["i32","i32",4,{"1":1,"2":2,"3":3,"4":4}],"-4":["i32","i32",4,{"-4":-4,"-3":-3,"-2":-2,"-1":-1}]}]}}';
-
-    self::$testArgsJSON['testInsanity'] = '{"0":{"map":["i64","map",2,{"1":["i32","rec",2,{"2":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}},"3":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}}}],"2":["i32","rec",1,{"6":{}}]}]}}';
-
-  }
-}
diff --git a/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php b/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
deleted file mode 100755
index 973f55c..0000000
--- a/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-
-/*
- * 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.
- *
- * @package thrift.test
- */
-
-namespace test\Thrift\Protocol;
-
-use Thrift\ClassLoader\ThriftClassLoader;
-use Test\Thrift\Fixtures;
-use Thrift\Transport\TMemoryBuffer;
-use Thrift\Protocol\TSimpleJSONProtocol;
-
-define( 'BUFSIZ', 8192 ); //big enough to read biggest serialized Fixture arg.
-
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
-
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
-$loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
-$loader->register();
-
-/***
- * This test suite depends on running the compiler against the
- * standard ThriftTest.thrift file:
- *
- * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r \
- *   --out ./packages ../../../test/ThriftTest.thrift
- */
-
-class TestTSimpleJSONProtocol extends \PHPUnit_Framework_TestCase
-{
-  private $transport;
-  private $protocol;
-
-  public static function setUpBeforeClass()
-  {
-    Fixtures::populateTestArgs();
-    TestTSimpleJSONProtocol_Fixtures::populateTestArgsSimpleJSON();
-  }
-
-  public function setUp()
-  {
-    $this->transport = new TMemoryBuffer();
-    $this->protocol = new TSimpleJSONProtocol($this->transport);
-    $this->transport->open();
-  }
-
-  /***
-   * WRITE TESTS
-   */
-
-  public function testVoid_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testVoid_args();
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testVoid'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testString1_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testString1'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testString1'];
-
-    #$this->assertEquals( $expected, $actual );
-  }
-
-  public function testString2_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testString_args();
-    $args->thing = Fixtures::$testArgs['testString2'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testString2'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testDouble_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testDouble_args();
-    $args->thing = Fixtures::$testArgs['testDouble'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testDouble'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testByte_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testByte_args();
-    $args->thing = Fixtures::$testArgs['testByte'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testByte'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI32_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testI32_args();
-    $args->thing = Fixtures::$testArgs['testI32'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testI32'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testI64_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testI64_args();
-    $args->thing = Fixtures::$testArgs['testI64'];
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testI64'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testStruct_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testStruct_args();
-    $args->thing = Fixtures::$testArgs['testStruct'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testStruct'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testNest_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testNest_args();
-    $args->thing = Fixtures::$testArgs['testNest'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testNest'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testMap_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testMap_args();
-    $args->thing = Fixtures::$testArgs['testMap'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testMap'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testStringMap_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testStringMap_args();
-    $args->thing = Fixtures::$testArgs['testStringMap'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testStringMap'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testSet_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testSet_args();
-    $args->thing = Fixtures::$testArgs['testSet'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testSet'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testList_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testList_args();
-    $args->thing = Fixtures::$testArgs['testList'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testList'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testEnum_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testEnum_args();
-    $args->thing = Fixtures::$testArgs['testEnum'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testEnum'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-
-  public function testTypedef_Write()
-  {
-    $args = new \ThriftTest\ThriftTest_testTypedef_args();
-    $args->thing = Fixtures::$testArgs['testTypedef'];
-
-    $args->write( $this->protocol );
-
-    $actual = $this->transport->read( BUFSIZ );
-    $expected = TestTSimpleJSONProtocol_Fixtures::$testArgsJSON['testTypedef'];
-
-    $this->assertEquals( $expected, $actual );
-  }
-}
-
-class TestTSimpleJSONProtocol_Fixtures
-{
-  public static $testArgsJSON = array();
-
-  public static function populateTestArgsSimpleJSON()
-  {
-    self::$testArgsJSON['testVoid'] = '{}';
-
-    self::$testArgsJSON['testString1'] = '{"1":{"str":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e"}}';
-
-    self::$testArgsJSON['testString2'] = '{"thing":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/  backspace: \\\\b formfeed: \f newline: \n return: \r tab:  now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}';
-
-    self::$testArgsJSON['testDouble'] = '{"thing":3.1415926535898}';
-
-    self::$testArgsJSON['testByte'] = '{"thing":1}';
-
-    self::$testArgsJSON['testI32'] = '{"thing":1073741824}';
-
-    if (PHP_INT_SIZE == 8) {
-      self::$testArgsJSON['testI64'] = '{"thing":'.pow( 2, 60 ).'}';
-      self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":'.pow( 2, 60 ).'}}';
-      self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":'.pow( 2, 60 ).'},"i32_thing":32768}}';
-    } else {
-      self::$testArgsJSON['testI64'] = '{"thing":1152921504606847000}';
-
-      self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000}}';
-      self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000},"i32_thing":32768}}';
-    }
-
-    self::$testArgsJSON['testMap'] = '{"thing":{"7":77,"8":88,"9":99}}';
-
-    self::$testArgsJSON['testStringMap'] = '{"thing":{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}}';
-
-    self::$testArgsJSON['testSet'] = '{"thing":[1,5,6]}';
-
-    self::$testArgsJSON['testList'] = '{"thing":[1,2,3]}';
-
-    self::$testArgsJSON['testEnum'] = '{"thing":1}';
-
-    self::$testArgsJSON['testTypedef'] = '{"thing":69}';
-  }
-}
diff --git a/lib/php/test/Test/Thrift/TestValidators.php b/lib/php/test/Test/Thrift/TestValidators.php
deleted file mode 100644
index 36cf000..0000000
--- a/lib/php/test/Test/Thrift/TestValidators.php
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-/*
- * 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.
- */
-
-namespace test\php;
-
-require_once __DIR__.'/../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
-
-use Thrift\ClassLoader\ThriftClassLoader;
-use Thrift\Exception\TProtocolException;
-use Thrift\Protocol\TBinaryProtocol;
-use Thrift\Transport\TMemoryBuffer;
-
-$oop_mode = (isset($argv[1]) && $argv[1] === '-oop');
-$GEN_DIR = $oop_mode ? 'phpvo' : 'phpv';
-
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../lib');
-$loader->registerDefinition('ThriftTest', __DIR__ . '/../../packages/' . $GEN_DIR);
-$loader->registerDefinition('TestValidators', __DIR__ . '/../../packages/' . $GEN_DIR);
-$loader->register();
-
-// Would be nice to have PHPUnit here, but for now just hack it.
-
-set_exception_handler(function ($e) {
-    my_assert(false, "Unexpected exception caught: " . $e->getMessage());
-});
-
-set_error_handler(function ($errno, $errmsg) {
-    my_assert(false, "Unexpected PHP error: " . $errmsg);
-});
-
-// Empty structs should not have validators
-assert_has_no_read_validator('ThriftTest\EmptyStruct');
-assert_has_no_write_validator('ThriftTest\EmptyStruct');
-
-// Bonk has only opt_in_req_out fields
-{
-    assert_has_no_read_validator('ThriftTest\Bonk');
-    assert_has_a_write_validator('ThriftTest\Bonk');
-    {
-        // Check that we can read an empty object
-        $bonk = new \ThriftTest\Bonk();
-        $transport = new TMemoryBuffer("\000");
-        $protocol = new TBinaryProtocol($transport);
-        $bonk->read($protocol);
-    }
-    {
-        // ...but not write an empty object
-        $bonk = new \ThriftTest\Bonk();
-        $transport = new TMemoryBuffer();
-        $protocol = new TBinaryProtocol($transport);
-        assert_protocol_exception_thrown(function () use ($bonk, $protocol) { $bonk->write($protocol); },
-                                         'Bonk was able to write an empty object');
-    }
-}
-
-// StructA has a single required field
-{
-    assert_has_a_read_validator('ThriftTest\StructA');
-    assert_has_a_write_validator('ThriftTest\StructA');
-    {
-        // Check that we are not able to write StructA with a missing required field
-        $structa = new \ThriftTest\StructA();
-        $transport = new TMemoryBuffer();
-        $protocol = new TBinaryProtocol($transport);
-        assert_protocol_exception_thrown(function () use ($structa, $protocol) { $structa->write($protocol); },
-                                         'StructA was able to write an empty object');
-    }
-    {
-        // Check that we are able to read and write a message with a good StructA
-        $transport = new TMemoryBuffer(base64_decode('CwABAAAAA2FiYwA='));
-        $protocol = new TBinaryProtocol($transport);
-        $structa = new \ThriftTest\StructA();
-        $structa->read($protocol);
-        $structa->write($protocol);
-    }
-}
-
-// Unions should not get write validators
-assert_has_no_write_validator('TestValidators\UnionOfStrings');
-
-// Service _result classes should not get any validators
-assert_has_no_read_validator('TestValidators\TestService_test_result');
-assert_has_no_write_validator('TestValidators\TestService_test_result');
-
-function assert_has_a_read_validator($class)
-{
-    my_assert(has_read_validator_method($class),
-              $class . ' class should have a read validator');
-}
-
-function assert_has_no_read_validator($class)
-{
-    my_assert(!has_read_validator_method($class),
-              $class . ' class should not have a read validator');
-}
-
-function assert_has_a_write_validator($class)
-{
-    my_assert(has_write_validator_method($class),
-              $class . ' class should have a write validator');
-}
-
-function assert_has_no_write_validator($class)
-{
-    my_assert(!has_write_validator_method($class),
-              $class . ' class should not have a write validator');
-}
-
-function assert_protocol_exception_thrown($callable, $message)
-{
-    try {
-        call_user_func($callable);
-        my_assert(false, $message);
-    } catch (TProtocolException $e) {
-    }
-}
-
-function has_write_validator_method($class)
-{
-    $rc = new \ReflectionClass($class);
-
-    return $rc->hasMethod('_validateForWrite');
-}
-
-function has_read_validator_method($class)
-{
-    $rc = new \ReflectionClass($class);
-
-    return $rc->hasMethod('_validateForRead');
-}
-
-function my_assert($something, $message)
-{
-    if (!$something) {
-        fwrite(STDERR, basename(__FILE__) . " FAILED: $message\n");
-        exit(1);
-    }
-}
diff --git a/lib/php/test/Validator/BaseValidatorTest.php b/lib/php/test/Validator/BaseValidatorTest.php
new file mode 100644
index 0000000..6029083
--- /dev/null
+++ b/lib/php/test/Validator/BaseValidatorTest.php
@@ -0,0 +1,154 @@
+<?php
+/*
+ * 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.
+ */
+
+namespace Test\Thrift;
+
+use PHPUnit\Framework\TestCase;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TBinaryProtocol;
+use Thrift\Transport\TMemoryBuffer;
+
+abstract class BaseValidatorTest extends TestCase
+{
+    public function testEmptyStructValidator()
+    {
+        $this->assertNoReadValidator('ThriftTest\EmptyStruct');
+        $this->assertNoWriteValidator('ThriftTest\EmptyStruct');
+    }
+
+    public function testBonkValidator()
+    {
+        $this->assertNoReadValidator('ThriftTest\Bonk');
+        $this->assertHasWriteValidator('ThriftTest\Bonk');
+    }
+
+    public function testStructAValidator()
+    {
+        $this->assertHasReadValidator('ThriftTest\StructA');
+        $this->assertHasWriteValidator('ThriftTest\StructA');
+    }
+
+    public function testUnionOfStringsValidator()
+    {
+        $this->assertNoWriteValidator('TestValidators\UnionOfStrings');
+    }
+
+    public function testServiceResultValidator()
+    {
+        $this->assertNoReadValidator('TestValidators\TestService_test_result');
+        $this->assertNoWriteValidator('TestValidators\TestService_test_result');
+    }
+
+    public function testReadEmpty()
+    {
+        $bonk = new \ThriftTest\Bonk();
+        $transport = new TMemoryBuffer("\000");
+        $protocol = new TBinaryProtocol($transport);
+        $bonk->read($protocol);
+    }
+
+    public function testWriteEmpty()
+    {
+        $bonk = new \ThriftTest\Bonk();
+        $transport = new TMemoryBuffer();
+        $protocol = new TBinaryProtocol($transport);
+        try {
+            $bonk->write($protocol);
+            $this->fail('Bonk was able to write an empty object');
+        } catch (TProtocolException $e) {
+        }
+    }
+
+    public function testWriteWithMissingRequired()
+    {
+        // Check that we are not able to write StructA with a missing required field
+        $structa = new \ThriftTest\StructA();
+        $transport = new TMemoryBuffer();
+        $protocol = new TBinaryProtocol($transport);
+
+        try {
+            $structa->write($protocol);
+            $this->fail('StructA was able to write an empty object');
+        } catch (TProtocolException $e) {
+        }
+    }
+
+    public function testReadStructA()
+    {
+        $transport = new TMemoryBuffer(base64_decode('CwABAAAAA2FiYwA='));
+        $protocol = new TBinaryProtocol($transport);
+        $structa = new \ThriftTest\StructA();
+        $structa->read($protocol);
+        $this->assertEquals("abc", $structa->s);
+    }
+
+    public function testWriteStructA()
+    {
+        $transport = new TMemoryBuffer();
+        $protocol = new TBinaryProtocol($transport);
+        $structa = new \ThriftTest\StructA();
+        $structa->s = "abc";
+        $structa->write($protocol);
+        $writeResult = base64_encode($transport->getBuffer());
+        $this->assertEquals('CwABAAAAA2FiYwA=', $writeResult);
+    }
+
+    protected static function assertHasReadValidator($class)
+    {
+        if (!static::hasReadValidator($class)) {
+            static::fail($class . ' class should have a read validator');
+        }
+    }
+
+    protected static function assertNoReadValidator($class)
+    {
+        if (static::hasReadValidator($class)) {
+            static::fail($class . ' class should not have a write validator');
+        }
+    }
+
+    protected static function assertHasWriteValidator($class)
+    {
+        if (!static::hasWriteValidator($class)) {
+            static::fail($class . ' class should have a write validator');
+        }
+    }
+
+    protected static function assertNoWriteValidator($class)
+    {
+        if (static::hasWriteValidator($class)) {
+            static::fail($class . ' class should not have a write validator');
+        }
+    }
+
+    private static function hasReadValidator($class)
+    {
+        $rc = new \ReflectionClass($class);
+
+        return $rc->hasMethod('_validateForRead');
+    }
+
+    private static function hasWriteValidator($class)
+    {
+        $rc = new \ReflectionClass($class);
+
+        return $rc->hasMethod('_validateForWrite');
+    }
+}
diff --git a/lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php b/lib/php/test/Validator/ValidatorTest.php
similarity index 63%
copy from lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php
copy to lib/php/test/Validator/ValidatorTest.php
index dcffbcb..fa6c7a9 100644
--- a/lib/php/lib/Thrift/Protocol/SimpleJSON/Context.php
+++ b/lib/php/test/Validator/ValidatorTest.php
@@ -16,21 +16,26 @@
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
- *
- * @package thrift.protocol
  */
 
-namespace Thrift\Protocol\SimpleJSON;
+namespace Test\Thrift;
 
-class Context
+require __DIR__ . '/../../../../vendor/autoload.php';
+
+use Thrift\ClassLoader\ThriftClassLoader;
+
+/**
+ * Class TestValidators
+ * @package Test\Thrift
+ *
+ * @runTestsInSeparateProcesses
+ */
+class ValidatorTest extends BaseValidatorTest
 {
-    public function write()
+    public function setUp()
     {
-    }
-
-    public function isMapKey()
-    {
-        return false;
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpv');
     }
 }
-
diff --git a/lib/php/lib/Thrift/Type/TType.php b/lib/php/test/Validator/ValidatorTestOop.php
similarity index 62%
copy from lib/php/lib/Thrift/Type/TType.php
copy to lib/php/test/Validator/ValidatorTestOop.php
index 71219c2..93bca4d 100644
--- a/lib/php/lib/Thrift/Type/TType.php
+++ b/lib/php/test/Validator/ValidatorTestOop.php
@@ -16,32 +16,26 @@
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
- *
- * @package thrift
  */
 
-namespace Thrift\Type;
+namespace Test\Thrift;
+
+require_once __DIR__ . '/../../../../vendor/autoload.php';
+
+use Thrift\ClassLoader\ThriftClassLoader;
 
 /**
- * Data types that can be sent via Thrift
+ * Class TestValidatorsOop
+ * @package Test\Thrift
+ *
+ * @runTestsInSeparateProcesses
  */
-class TType
+class ValidatorTestOop extends BaseValidatorTest
 {
-  const STOP   = 0;
-  const VOID   = 1;
-  const BOOL   = 2;
-  const BYTE   = 3;
-  const I08    = 3;
-  const DOUBLE = 4;
-  const I16    = 6;
-  const I32    = 8;
-  const I64    = 10;
-  const STRING = 11;
-  const UTF7   = 11;
-  const STRUCT = 12;
-  const MAP    = 13;
-  const SET    = 14;
-  const LST    = 15;    // N.B. cannot use LIST keyword in PHP!
-  const UTF8   = 16;
-  const UTF16  = 17;
+    public function setUp()
+    {
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpvo');
+    }
 }
diff --git a/lib/py/setup.py b/lib/py/setup.py
index e3435c7..3cf1469 100644
--- a/lib/py/setup.py
+++ b/lib/py/setup.py
@@ -31,7 +31,10 @@
 # Fix to build sdist under vagrant
 import os
 if 'vagrant' in str(os.environ):
-    del os.link
+    try:
+        del os.link
+    except AttributeError:
+        pass
 
 include_dirs = ['src']
 if sys.platform == 'win32':
@@ -87,9 +90,9 @@
     twisted_deps = ['twisted']
 
     setup(name='thrift',
-          version='0.11.0',
+          version='1.0.0',
           description='Python bindings for the Apache Thrift RPC system',
-          author='Thrift Developers',
+          author='Apache Thrift Developers',
           author_email='dev@thrift.apache.org',
           url='http://thrift.apache.org',
           license='Apache License 2.0',
diff --git a/lib/py/src/TMultiplexedProcessor.py b/lib/py/src/TMultiplexedProcessor.py
index 605aa1f..3ac5af0 100644
--- a/lib/py/src/TMultiplexedProcessor.py
+++ b/lib/py/src/TMultiplexedProcessor.py
@@ -31,11 +31,11 @@
     def process(self, iprot, oprot):
         (name, type, seqid) = iprot.readMessageBegin()
         if type != TMessageType.CALL and type != TMessageType.ONEWAY:
-            raise TException("TMultiplex protocol only supports CALL & ONEWAY")
+            raise TException("TMultiplexed protocol only supports CALL & ONEWAY")
 
         index = name.find(TMultiplexedProtocol.SEPARATOR)
         if index < 0:
-            raise TException("Service name not found in message name: " + name + ". Did you forget to use TMultiplexProtocol in your client?")
+            raise TException("Service name not found in message name: " + name + ". Did you forget to use TMultiplexedProtocol in your client?")
 
         serviceName = name[0:index]
         call = name[index + len(TMultiplexedProtocol.SEPARATOR):]
@@ -48,7 +48,6 @@
 
 class StoredMessageProtocol(TProtocolDecorator.TProtocolDecorator):
     def __init__(self, protocol, messageBegin):
-        TProtocolDecorator.TProtocolDecorator.__init__(self, protocol)
         self.messageBegin = messageBegin
 
     def readMessageBegin(self):
diff --git a/lib/py/src/compat.py b/lib/py/src/compat.py
index 41bcf35..0e8271d 100644
--- a/lib/py/src/compat.py
+++ b/lib/py/src/compat.py
@@ -29,6 +29,9 @@
     def str_to_binary(str_val):
         return str_val
 
+    def byte_index(bytes_val, i):
+        return ord(bytes_val[i])
+
 else:
 
     from io import BytesIO as BufferIO  # noqa
@@ -38,3 +41,6 @@
 
     def str_to_binary(str_val):
         return bytes(str_val, 'utf8')
+
+    def byte_index(bytes_val, i):
+        return bytes_val[i]
diff --git a/lib/py/src/ext/protocol.h b/lib/py/src/ext/protocol.h
index 126dbc3..521b7ee 100644
--- a/lib/py/src/ext/protocol.h
+++ b/lib/py/src/ext/protocol.h
@@ -33,8 +33,8 @@
 
 public:
   ProtocolBase()
-    : stringLimit_(std::numeric_limits<int32_t>::max()),
-      containerLimit_(std::numeric_limits<int32_t>::max()),
+    : stringLimit_((std::numeric_limits<int32_t>::max)()),
+      containerLimit_((std::numeric_limits<int32_t>::max)()),
       output_(NULL) {}
   inline virtual ~ProtocolBase();
 
diff --git a/lib/py/src/ext/protocol.tcc b/lib/py/src/ext/protocol.tcc
index c025d0c..e15df7e 100644
--- a/lib/py/src/ext/protocol.tcc
+++ b/lib/py/src/ext/protocol.tcc
@@ -144,7 +144,7 @@
   *output = PyBytes_AS_STRING(buf2->buf) + buf2->pos;
 #endif
   Py_ssize_t pos0 = buf2->pos;
-  buf2->pos = std::min(buf2->pos + static_cast<Py_ssize_t>(len), buf2->string_size);
+  buf2->pos = (std::min)(buf2->pos + static_cast<Py_ssize_t>(len), buf2->string_size);
   return static_cast<int>(buf2->pos - pos0);
 }
 }
@@ -212,7 +212,7 @@
   if (INT_CONV_ERROR_OCCURRED(len)) {
     return false;
   }
-  if (!CHECK_RANGE(len, 0, std::numeric_limits<int32_t>::max())) {
+  if (!CHECK_RANGE(len, 0, (std::numeric_limits<int32_t>::max)())) {
     PyErr_SetString(PyExc_OverflowError, "size out of range: exceeded INT32_MAX");
     return false;
   }
@@ -360,8 +360,8 @@
   case T_I08: {
     int8_t val;
 
-    if (!parse_pyint(value, &val, std::numeric_limits<int8_t>::min(),
-                     std::numeric_limits<int8_t>::max())) {
+    if (!parse_pyint(value, &val, (std::numeric_limits<int8_t>::min)(),
+                     (std::numeric_limits<int8_t>::max)())) {
       return false;
     }
 
@@ -371,8 +371,8 @@
   case T_I16: {
     int16_t val;
 
-    if (!parse_pyint(value, &val, std::numeric_limits<int16_t>::min(),
-                     std::numeric_limits<int16_t>::max())) {
+    if (!parse_pyint(value, &val, (std::numeric_limits<int16_t>::min)(),
+                     (std::numeric_limits<int16_t>::max)())) {
       return false;
     }
 
@@ -382,8 +382,8 @@
   case T_I32: {
     int32_t val;
 
-    if (!parse_pyint(value, &val, std::numeric_limits<int32_t>::min(),
-                     std::numeric_limits<int32_t>::max())) {
+    if (!parse_pyint(value, &val, (std::numeric_limits<int32_t>::min)(),
+                     (std::numeric_limits<int32_t>::max)())) {
       return false;
     }
 
@@ -397,8 +397,8 @@
       return false;
     }
 
-    if (!CHECK_RANGE(nval, std::numeric_limits<int64_t>::min(),
-                     std::numeric_limits<int64_t>::max())) {
+    if (!CHECK_RANGE(nval, (std::numeric_limits<int64_t>::min)(),
+                     (std::numeric_limits<int64_t>::max)())) {
       PyErr_SetString(PyExc_OverflowError, "int out of range");
       return false;
     }
diff --git a/lib/py/src/protocol/THeaderProtocol.py b/lib/py/src/protocol/THeaderProtocol.py
new file mode 100644
index 0000000..b27a749
--- /dev/null
+++ b/lib/py/src/protocol/THeaderProtocol.py
@@ -0,0 +1,225 @@
+#
+# 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.
+#
+
+from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated
+from thrift.protocol.TCompactProtocol import TCompactProtocolAccelerated
+from thrift.protocol.TProtocol import TProtocolBase, TProtocolException
+from thrift.Thrift import TApplicationException, TMessageType
+from thrift.transport.THeaderTransport import THeaderTransport, THeaderSubprotocolID, THeaderClientType
+
+
+PROTOCOLS_BY_ID = {
+    THeaderSubprotocolID.BINARY: TBinaryProtocolAccelerated,
+    THeaderSubprotocolID.COMPACT: TCompactProtocolAccelerated,
+}
+
+
+class THeaderProtocol(TProtocolBase):
+    """A framed protocol with headers and payload transforms.
+
+    THeaderProtocol frames other Thrift protocols and adds support for optional
+    out-of-band headers. The currently supported subprotocols are
+    TBinaryProtocol and TCompactProtocol.
+
+    It's also possible to apply transforms to the encoded message payload. The
+    only transform currently supported is to gzip.
+
+    When used in a server, THeaderProtocol can accept messages from
+    non-THeaderProtocol clients if allowed (see `allowed_client_types`). This
+    includes framed and unframed transports and both TBinaryProtocol and
+    TCompactProtocol. The server will respond in the appropriate dialect for
+    the connected client. HTTP clients are not currently supported.
+
+    THeaderProtocol does not currently support THTTPServer, TNonblockingServer,
+    or TProcessPoolServer.
+
+    See doc/specs/HeaderFormat.md for details of the wire format.
+
+    """
+
+    def __init__(self, transport, allowed_client_types):
+        # much of the actual work for THeaderProtocol happens down in
+        # THeaderTransport since we need to do low-level shenanigans to detect
+        # if the client is sending us headers or one of the headerless formats
+        # we support. this wraps the real transport with the one that does all
+        # the magic.
+        if not isinstance(transport, THeaderTransport):
+            transport = THeaderTransport(transport, allowed_client_types)
+        super(THeaderProtocol, self).__init__(transport)
+        self._set_protocol()
+
+    def get_headers(self):
+        return self.trans.get_headers()
+
+    def set_header(self, key, value):
+        self.trans.set_header(key, value)
+
+    def clear_headers(self):
+        self.trans.clear_headers()
+
+    def add_transform(self, transform_id):
+        self.trans.add_transform(transform_id)
+
+    def writeMessageBegin(self, name, ttype, seqid):
+        self.trans.sequence_id = seqid
+        return self._protocol.writeMessageBegin(name, ttype, seqid)
+
+    def writeMessageEnd(self):
+        return self._protocol.writeMessageEnd()
+
+    def writeStructBegin(self, name):
+        return self._protocol.writeStructBegin(name)
+
+    def writeStructEnd(self):
+        return self._protocol.writeStructEnd()
+
+    def writeFieldBegin(self, name, ttype, fid):
+        return self._protocol.writeFieldBegin(name, ttype, fid)
+
+    def writeFieldEnd(self):
+        return self._protocol.writeFieldEnd()
+
+    def writeFieldStop(self):
+        return self._protocol.writeFieldStop()
+
+    def writeMapBegin(self, ktype, vtype, size):
+        return self._protocol.writeMapBegin(ktype, vtype, size)
+
+    def writeMapEnd(self):
+        return self._protocol.writeMapEnd()
+
+    def writeListBegin(self, etype, size):
+        return self._protocol.writeListBegin(etype, size)
+
+    def writeListEnd(self):
+        return self._protocol.writeListEnd()
+
+    def writeSetBegin(self, etype, size):
+        return self._protocol.writeSetBegin(etype, size)
+
+    def writeSetEnd(self):
+        return self._protocol.writeSetEnd()
+
+    def writeBool(self, bool_val):
+        return self._protocol.writeBool(bool_val)
+
+    def writeByte(self, byte):
+        return self._protocol.writeByte(byte)
+
+    def writeI16(self, i16):
+        return self._protocol.writeI16(i16)
+
+    def writeI32(self, i32):
+        return self._protocol.writeI32(i32)
+
+    def writeI64(self, i64):
+        return self._protocol.writeI64(i64)
+
+    def writeDouble(self, dub):
+        return self._protocol.writeDouble(dub)
+
+    def writeBinary(self, str_val):
+        return self._protocol.writeBinary(str_val)
+
+    def _set_protocol(self):
+        try:
+            protocol_cls = PROTOCOLS_BY_ID[self.trans.protocol_id]
+        except KeyError:
+            raise TApplicationException(
+                TProtocolException.INVALID_PROTOCOL,
+                "Unknown protocol requested.",
+            )
+
+        self._protocol = protocol_cls(self.trans)
+        self._fast_encode = self._protocol._fast_encode
+        self._fast_decode = self._protocol._fast_decode
+
+    def readMessageBegin(self):
+        try:
+            self.trans.readFrame(0)
+            self._set_protocol()
+        except TApplicationException as exc:
+            self._protocol.writeMessageBegin(b"", TMessageType.EXCEPTION, 0)
+            exc.write(self._protocol)
+            self._protocol.writeMessageEnd()
+            self.trans.flush()
+
+        return self._protocol.readMessageBegin()
+
+    def readMessageEnd(self):
+        return self._protocol.readMessageEnd()
+
+    def readStructBegin(self):
+        return self._protocol.readStructBegin()
+
+    def readStructEnd(self):
+        return self._protocol.readStructEnd()
+
+    def readFieldBegin(self):
+        return self._protocol.readFieldBegin()
+
+    def readFieldEnd(self):
+        return self._protocol.readFieldEnd()
+
+    def readMapBegin(self):
+        return self._protocol.readMapBegin()
+
+    def readMapEnd(self):
+        return self._protocol.readMapEnd()
+
+    def readListBegin(self):
+        return self._protocol.readListBegin()
+
+    def readListEnd(self):
+        return self._protocol.readListEnd()
+
+    def readSetBegin(self):
+        return self._protocol.readSetBegin()
+
+    def readSetEnd(self):
+        return self._protocol.readSetEnd()
+
+    def readBool(self):
+        return self._protocol.readBool()
+
+    def readByte(self):
+        return self._protocol.readByte()
+
+    def readI16(self):
+        return self._protocol.readI16()
+
+    def readI32(self):
+        return self._protocol.readI32()
+
+    def readI64(self):
+        return self._protocol.readI64()
+
+    def readDouble(self):
+        return self._protocol.readDouble()
+
+    def readBinary(self):
+        return self._protocol.readBinary()
+
+
+class THeaderProtocolFactory(object):
+    def __init__(self, allowed_client_types=(THeaderClientType.HEADERS,)):
+        self.allowed_client_types = allowed_client_types
+
+    def getProtocol(self, trans):
+        return THeaderProtocol(trans, self.allowed_client_types)
diff --git a/lib/py/src/protocol/TMultiplexedProtocol.py b/lib/py/src/protocol/TMultiplexedProtocol.py
index 309f896..0f8390f 100644
--- a/lib/py/src/protocol/TMultiplexedProtocol.py
+++ b/lib/py/src/protocol/TMultiplexedProtocol.py
@@ -25,16 +25,15 @@
 
 class TMultiplexedProtocol(TProtocolDecorator.TProtocolDecorator):
     def __init__(self, protocol, serviceName):
-        TProtocolDecorator.TProtocolDecorator.__init__(self, protocol)
         self.serviceName = serviceName
 
     def writeMessageBegin(self, name, type, seqid):
         if (type == TMessageType.CALL or
                 type == TMessageType.ONEWAY):
-            self.protocol.writeMessageBegin(
+            super(TMultiplexedProtocol, self).writeMessageBegin(
                 self.serviceName + SEPARATOR + name,
                 type,
                 seqid
             )
         else:
-            self.protocol.writeMessageBegin(name, type, seqid)
+            super(TMultiplexedProtocol, self).writeMessageBegin(name, type, seqid)
diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py
index fd20cb7..8314cf6 100644
--- a/lib/py/src/protocol/TProtocol.py
+++ b/lib/py/src/protocol/TProtocol.py
@@ -37,6 +37,7 @@
     BAD_VERSION = 4
     NOT_IMPLEMENTED = 5
     DEPTH_LIMIT = 6
+    INVALID_PROTOCOL = 7
 
     def __init__(self, type=UNKNOWN, message=None):
         TException.__init__(self, message)
diff --git a/lib/py/src/protocol/TProtocolDecorator.py b/lib/py/src/protocol/TProtocolDecorator.py
index 8b270a4..f5546c7 100644
--- a/lib/py/src/protocol/TProtocolDecorator.py
+++ b/lib/py/src/protocol/TProtocolDecorator.py
@@ -17,34 +17,10 @@
 # under the License.
 #
 
-import types
 
-from thrift.protocol.TProtocol import TProtocolBase
-
-
-class TProtocolDecorator():
-    def __init__(self, protocol):
-        TProtocolBase(protocol)
-        self.protocol = protocol
-
-    def __getattr__(self, name):
-        if hasattr(self.protocol, name):
-            member = getattr(self.protocol, name)
-            if type(member) in [
-                types.MethodType,
-                types.FunctionType,
-                types.LambdaType,
-                types.BuiltinFunctionType,
-                types.BuiltinMethodType,
-            ]:
-                return lambda *args, **kwargs: self._wrap(member, args, kwargs)
-            else:
-                return member
-        raise AttributeError(name)
-
-    def _wrap(self, func, args, kwargs):
-        if isinstance(func, types.MethodType):
-            result = func(*args, **kwargs)
-        else:
-            result = func(self.protocol, *args, **kwargs)
-        return result
+class TProtocolDecorator(object):
+    def __new__(cls, protocol, *args, **kwargs):
+        decorated_cls = type(''.join(['Decorated', protocol.__class__.__name__]),
+                             (cls, protocol.__class__),
+                             protocol.__dict__)
+        return object.__new__(decorated_cls)
diff --git a/lib/py/src/server/THttpServer.py b/lib/py/src/server/THttpServer.py
index 1b501a7..85cf400 100644
--- a/lib/py/src/server/THttpServer.py
+++ b/lib/py/src/server/THttpServer.py
@@ -17,6 +17,8 @@
 # under the License.
 #
 
+import ssl
+
 from six.moves import BaseHTTPServer
 
 from thrift.server import TServer
@@ -47,11 +49,17 @@
                  server_address,
                  inputProtocolFactory,
                  outputProtocolFactory=None,
-                 server_class=BaseHTTPServer.HTTPServer):
-        """Set up protocol factories and HTTP server.
+                 server_class=BaseHTTPServer.HTTPServer,
+                 **kwargs):
+        """Set up protocol factories and HTTP (or HTTPS) server.
 
         See BaseHTTPServer for server_address.
         See TServer for protocol factories.
+
+        To make a secure server, provide the named arguments:
+        * cafile    - to validate clients [optional]
+        * cert_file - the server cert
+        * key_file  - the server's key
         """
         if outputProtocolFactory is None:
             outputProtocolFactory = inputProtocolFactory
@@ -83,5 +91,16 @@
 
         self.httpd = server_class(server_address, RequestHander)
 
+        if (kwargs.get('cafile') or kwargs.get('cert_file') or kwargs.get('key_file')):
+            context = ssl.create_default_context(cafile=kwargs.get('cafile'))
+            context.check_hostname = False
+            context.load_cert_chain(kwargs.get('cert_file'), kwargs.get('key_file'))
+            context.verify_mode = ssl.CERT_REQUIRED if kwargs.get('cafile') else ssl.CERT_NONE
+            self.httpd.socket = context.wrap_socket(self.httpd.socket, server_side=True)
+
     def serve(self):
         self.httpd.serve_forever()
+
+    def shutdown(self):
+        self.httpd.socket.close()
+        # self.httpd.shutdown() # hangs forever, python doesn't handle POLLNVAL properly!
diff --git a/lib/py/src/server/TNonblockingServer.py b/lib/py/src/server/TNonblockingServer.py
index 26c0f7e..f62d486 100644
--- a/lib/py/src/server/TNonblockingServer.py
+++ b/lib/py/src/server/TNonblockingServer.py
@@ -174,7 +174,7 @@
             self._wbuf = b''
             self.len = 0
         else:
-            self._wbuf = self.message[sent:]
+            self._wbuf = self._wbuf[sent:]
 
     @locked
     def ready(self, all_ok, message):
diff --git a/lib/py/src/server/TServer.py b/lib/py/src/server/TServer.py
index d5d9c98..df2a7bb 100644
--- a/lib/py/src/server/TServer.py
+++ b/lib/py/src/server/TServer.py
@@ -23,6 +23,7 @@
 import threading
 
 from thrift.protocol import TBinaryProtocol
+from thrift.protocol.THeaderProtocol import THeaderProtocolFactory
 from thrift.transport import TTransport
 
 logger = logging.getLogger(__name__)
@@ -60,6 +61,12 @@
         self.inputProtocolFactory = inputProtocolFactory
         self.outputProtocolFactory = outputProtocolFactory
 
+        input_is_header = isinstance(self.inputProtocolFactory, THeaderProtocolFactory)
+        output_is_header = isinstance(self.outputProtocolFactory, THeaderProtocolFactory)
+        if any((input_is_header, output_is_header)) and input_is_header != output_is_header:
+            raise ValueError("THeaderProtocol servers require that both the input and "
+                             "output protocols are THeaderProtocol.")
+
     def serve(self):
         pass
 
@@ -76,10 +83,20 @@
             client = self.serverTransport.accept()
             if not client:
                 continue
+
             itrans = self.inputTransportFactory.getTransport(client)
-            otrans = self.outputTransportFactory.getTransport(client)
             iprot = self.inputProtocolFactory.getProtocol(itrans)
-            oprot = self.outputProtocolFactory.getProtocol(otrans)
+
+            # for THeaderProtocol, we must use the same protocol instance for
+            # input and output so that the response is in the same dialect that
+            # the server detected the request was in.
+            if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
+                otrans = None
+                oprot = iprot
+            else:
+                otrans = self.outputTransportFactory.getTransport(client)
+                oprot = self.outputProtocolFactory.getProtocol(otrans)
+
             try:
                 while True:
                     self.processor.process(iprot, oprot)
@@ -89,7 +106,8 @@
                 logger.exception(x)
 
             itrans.close()
-            otrans.close()
+            if otrans:
+                otrans.close()
 
 
 class TThreadedServer(TServer):
@@ -116,9 +134,18 @@
 
     def handle(self, client):
         itrans = self.inputTransportFactory.getTransport(client)
-        otrans = self.outputTransportFactory.getTransport(client)
         iprot = self.inputProtocolFactory.getProtocol(itrans)
-        oprot = self.outputProtocolFactory.getProtocol(otrans)
+
+        # for THeaderProtocol, we must use the same protocol instance for input
+        # and output so that the response is in the same dialect that the
+        # server detected the request was in.
+        if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
+            otrans = None
+            oprot = iprot
+        else:
+            otrans = self.outputTransportFactory.getTransport(client)
+            oprot = self.outputProtocolFactory.getProtocol(otrans)
+
         try:
             while True:
                 self.processor.process(iprot, oprot)
@@ -128,7 +155,8 @@
             logger.exception(x)
 
         itrans.close()
-        otrans.close()
+        if otrans:
+            otrans.close()
 
 
 class TThreadPoolServer(TServer):
@@ -156,9 +184,18 @@
     def serveClient(self, client):
         """Process input/output from a client for as long as possible"""
         itrans = self.inputTransportFactory.getTransport(client)
-        otrans = self.outputTransportFactory.getTransport(client)
         iprot = self.inputProtocolFactory.getProtocol(itrans)
-        oprot = self.outputProtocolFactory.getProtocol(otrans)
+
+        # for THeaderProtocol, we must use the same protocol instance for input
+        # and output so that the response is in the same dialect that the
+        # server detected the request was in.
+        if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
+            otrans = None
+            oprot = iprot
+        else:
+            otrans = self.outputTransportFactory.getTransport(client)
+            oprot = self.outputProtocolFactory.getProtocol(otrans)
+
         try:
             while True:
                 self.processor.process(iprot, oprot)
@@ -168,7 +205,8 @@
             logger.exception(x)
 
         itrans.close()
-        otrans.close()
+        if otrans:
+            otrans.close()
 
     def serve(self):
         """Start a fixed number of worker threads and put client into a queue"""
@@ -237,10 +275,18 @@
                     try_close(otrans)
                 else:
                     itrans = self.inputTransportFactory.getTransport(client)
-                    otrans = self.outputTransportFactory.getTransport(client)
-
                     iprot = self.inputProtocolFactory.getProtocol(itrans)
-                    oprot = self.outputProtocolFactory.getProtocol(otrans)
+
+                    # for THeaderProtocol, we must use the same protocol
+                    # instance for input and output so that the response is in
+                    # the same dialect that the server detected the request was
+                    # in.
+                    if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
+                        otrans = None
+                        oprot = iprot
+                    else:
+                        otrans = self.outputTransportFactory.getTransport(client)
+                        oprot = self.outputProtocolFactory.getProtocol(otrans)
 
                     ecode = 0
                     try:
@@ -254,7 +300,8 @@
                             ecode = 1
                     finally:
                         try_close(itrans)
-                        try_close(otrans)
+                        if otrans:
+                            try_close(otrans)
 
                     os._exit(ecode)
 
diff --git a/lib/py/src/transport/THeaderTransport.py b/lib/py/src/transport/THeaderTransport.py
new file mode 100644
index 0000000..c0d5640
--- /dev/null
+++ b/lib/py/src/transport/THeaderTransport.py
@@ -0,0 +1,352 @@
+#
+# 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 struct
+import zlib
+
+from thrift.compat import BufferIO, byte_index
+from thrift.protocol.TBinaryProtocol import TBinaryProtocol
+from thrift.protocol.TCompactProtocol import TCompactProtocol, readVarint, writeVarint
+from thrift.Thrift import TApplicationException
+from thrift.transport.TTransport import (
+    CReadableTransport,
+    TMemoryBuffer,
+    TTransportBase,
+    TTransportException,
+)
+
+
+U16 = struct.Struct("!H")
+I32 = struct.Struct("!i")
+HEADER_MAGIC = 0x0FFF
+HARD_MAX_FRAME_SIZE = 0x3FFFFFFF
+
+
+class THeaderClientType(object):
+    HEADERS = 0x00
+
+    FRAMED_BINARY = 0x01
+    UNFRAMED_BINARY = 0x02
+
+    FRAMED_COMPACT = 0x03
+    UNFRAMED_COMPACT = 0x04
+
+
+class THeaderSubprotocolID(object):
+    BINARY = 0x00
+    COMPACT = 0x02
+
+
+class TInfoHeaderType(object):
+    KEY_VALUE = 0x01
+
+
+class THeaderTransformID(object):
+    ZLIB = 0x01
+
+
+READ_TRANSFORMS_BY_ID = {
+    THeaderTransformID.ZLIB: zlib.decompress,
+}
+
+
+WRITE_TRANSFORMS_BY_ID = {
+    THeaderTransformID.ZLIB: zlib.compress,
+}
+
+
+def _readString(trans):
+    size = readVarint(trans)
+    if size < 0:
+        raise TTransportException(
+            TTransportException.NEGATIVE_SIZE,
+            "Negative length"
+        )
+    return trans.read(size)
+
+
+def _writeString(trans, value):
+    writeVarint(trans, len(value))
+    trans.write(value)
+
+
+class THeaderTransport(TTransportBase, CReadableTransport):
+    def __init__(self, transport, allowed_client_types):
+        self._transport = transport
+        self._client_type = THeaderClientType.HEADERS
+        self._allowed_client_types = allowed_client_types
+
+        self._read_buffer = BufferIO(b"")
+        self._read_headers = {}
+
+        self._write_buffer = BufferIO()
+        self._write_headers = {}
+        self._write_transforms = []
+
+        self.flags = 0
+        self.sequence_id = 0
+        self._protocol_id = THeaderSubprotocolID.BINARY
+        self._max_frame_size = HARD_MAX_FRAME_SIZE
+
+    def isOpen(self):
+        return self._transport.isOpen()
+
+    def open(self):
+        return self._transport.open()
+
+    def close(self):
+        return self._transport.close()
+
+    def get_headers(self):
+        return self._read_headers
+
+    def set_header(self, key, value):
+        if not isinstance(key, bytes):
+            raise ValueError("header names must be bytes")
+        if not isinstance(value, bytes):
+            raise ValueError("header values must be bytes")
+        self._write_headers[key] = value
+
+    def clear_headers(self):
+        self._write_headers.clear()
+
+    def add_transform(self, transform_id):
+        if transform_id not in WRITE_TRANSFORMS_BY_ID:
+            raise ValueError("unknown transform")
+        self._write_transforms.append(transform_id)
+
+    def set_max_frame_size(self, size):
+        if not 0 < size < HARD_MAX_FRAME_SIZE:
+            raise ValueError("maximum frame size should be < %d and > 0" % HARD_MAX_FRAME_SIZE)
+        self._max_frame_size = size
+
+    @property
+    def protocol_id(self):
+        if self._client_type == THeaderClientType.HEADERS:
+            return self._protocol_id
+        elif self._client_type in (THeaderClientType.FRAMED_BINARY, THeaderClientType.UNFRAMED_BINARY):
+            return THeaderSubprotocolID.BINARY
+        elif self._client_type in (THeaderClientType.FRAMED_COMPACT, THeaderClientType.UNFRAMED_COMPACT):
+            return THeaderSubprotocolID.COMPACT
+        else:
+            raise TTransportException(
+                TTransportException.INVALID_CLIENT_TYPE,
+                "Protocol ID not know for client type %d" % self._client_type,
+            )
+
+    def read(self, sz):
+        # if there are bytes left in the buffer, produce those first.
+        bytes_read = self._read_buffer.read(sz)
+        bytes_left_to_read = sz - len(bytes_read)
+        if bytes_left_to_read == 0:
+            return bytes_read
+
+        # if we've determined this is an unframed client, just pass the read
+        # through to the underlying transport until we're reset again at the
+        # beginning of the next message.
+        if self._client_type in (THeaderClientType.UNFRAMED_BINARY, THeaderClientType.UNFRAMED_COMPACT):
+            return bytes_read + self._transport.read(bytes_left_to_read)
+
+        # we're empty and (maybe) framed. fill the buffers with the next frame.
+        self.readFrame(bytes_left_to_read)
+        return bytes_read + self._read_buffer.read(bytes_left_to_read)
+
+    def _set_client_type(self, client_type):
+        if client_type not in self._allowed_client_types:
+            raise TTransportException(
+                TTransportException.INVALID_CLIENT_TYPE,
+                "Client type %d not allowed by server." % client_type,
+            )
+        self._client_type = client_type
+
+    def readFrame(self, req_sz):
+        # the first word could either be the length field of a framed message
+        # or the first bytes of an unframed message.
+        first_word = self._transport.readAll(I32.size)
+        frame_size, = I32.unpack(first_word)
+        is_unframed = False
+        if frame_size & TBinaryProtocol.VERSION_MASK == TBinaryProtocol.VERSION_1:
+            self._set_client_type(THeaderClientType.UNFRAMED_BINARY)
+            is_unframed = True
+        elif (byte_index(first_word, 0) == TCompactProtocol.PROTOCOL_ID and
+              byte_index(first_word, 1) & TCompactProtocol.VERSION_MASK == TCompactProtocol.VERSION):
+            self._set_client_type(THeaderClientType.UNFRAMED_COMPACT)
+            is_unframed = True
+
+        if is_unframed:
+            bytes_left_to_read = req_sz - I32.size
+            if bytes_left_to_read > 0:
+                rest = self._transport.read(bytes_left_to_read)
+            else:
+                rest = b""
+            self._read_buffer = BufferIO(first_word + rest)
+            return
+
+        # ok, we're still here so we're framed.
+        if frame_size > self._max_frame_size:
+            raise TTransportException(
+                TTransportException.SIZE_LIMIT,
+                "Frame was too large.",
+            )
+        read_buffer = BufferIO(self._transport.readAll(frame_size))
+
+        # the next word is either going to be the version field of a
+        # binary/compact protocol message or the magic value + flags of a
+        # header protocol message.
+        second_word = read_buffer.read(I32.size)
+        version, = I32.unpack(second_word)
+        read_buffer.seek(0)
+        if version >> 16 == HEADER_MAGIC:
+            self._set_client_type(THeaderClientType.HEADERS)
+            self._read_buffer = self._parse_header_format(read_buffer)
+        elif version & TBinaryProtocol.VERSION_MASK == TBinaryProtocol.VERSION_1:
+            self._set_client_type(THeaderClientType.FRAMED_BINARY)
+            self._read_buffer = read_buffer
+        elif (byte_index(second_word, 0) == TCompactProtocol.PROTOCOL_ID and
+              byte_index(second_word, 1) & TCompactProtocol.VERSION_MASK == TCompactProtocol.VERSION):
+            self._set_client_type(THeaderClientType.FRAMED_COMPACT)
+            self._read_buffer = read_buffer
+        else:
+            raise TTransportException(
+                TTransportException.INVALID_CLIENT_TYPE,
+                "Could not detect client transport type.",
+            )
+
+    def _parse_header_format(self, buffer):
+        # make BufferIO look like TTransport for varint helpers
+        buffer_transport = TMemoryBuffer()
+        buffer_transport._buffer = buffer
+
+        buffer.read(2)  # discard the magic bytes
+        self.flags, = U16.unpack(buffer.read(U16.size))
+        self.sequence_id, = I32.unpack(buffer.read(I32.size))
+
+        header_length = U16.unpack(buffer.read(U16.size))[0] * 4
+        end_of_headers = buffer.tell() + header_length
+        if end_of_headers > len(buffer.getvalue()):
+            raise TTransportException(
+                TTransportException.SIZE_LIMIT,
+                "Header size is larger than whole frame.",
+            )
+
+        self._protocol_id = readVarint(buffer_transport)
+
+        transforms = []
+        transform_count = readVarint(buffer_transport)
+        for _ in range(transform_count):
+            transform_id = readVarint(buffer_transport)
+            if transform_id not in READ_TRANSFORMS_BY_ID:
+                raise TApplicationException(
+                    TApplicationException.INVALID_TRANSFORM,
+                    "Unknown transform: %d" % transform_id,
+                )
+            transforms.append(transform_id)
+        transforms.reverse()
+
+        headers = {}
+        while buffer.tell() < end_of_headers:
+            header_type = readVarint(buffer_transport)
+            if header_type == TInfoHeaderType.KEY_VALUE:
+                count = readVarint(buffer_transport)
+                for _ in range(count):
+                    key = _readString(buffer_transport)
+                    value = _readString(buffer_transport)
+                    headers[key] = value
+            else:
+                break  # ignore unknown headers
+        self._read_headers = headers
+
+        # skip padding / anything we didn't understand
+        buffer.seek(end_of_headers)
+
+        payload = buffer.read()
+        for transform_id in transforms:
+            transform_fn = READ_TRANSFORMS_BY_ID[transform_id]
+            payload = transform_fn(payload)
+        return BufferIO(payload)
+
+    def write(self, buf):
+        self._write_buffer.write(buf)
+
+    def flush(self):
+        payload = self._write_buffer.getvalue()
+        self._write_buffer = BufferIO()
+
+        buffer = BufferIO()
+        if self._client_type == THeaderClientType.HEADERS:
+            for transform_id in self._write_transforms:
+                transform_fn = WRITE_TRANSFORMS_BY_ID[transform_id]
+                payload = transform_fn(payload)
+
+            headers = BufferIO()
+            writeVarint(headers, self._protocol_id)
+            writeVarint(headers, len(self._write_transforms))
+            for transform_id in self._write_transforms:
+                writeVarint(headers, transform_id)
+            if self._write_headers:
+                writeVarint(headers, TInfoHeaderType.KEY_VALUE)
+                writeVarint(headers, len(self._write_headers))
+                for key, value in self._write_headers.items():
+                    _writeString(headers, key)
+                    _writeString(headers, value)
+                self._write_headers = {}
+            padding_needed = (4 - (len(headers.getvalue()) % 4)) % 4
+            headers.write(b"\x00" * padding_needed)
+            header_bytes = headers.getvalue()
+
+            buffer.write(I32.pack(10 + len(header_bytes) + len(payload)))
+            buffer.write(U16.pack(HEADER_MAGIC))
+            buffer.write(U16.pack(self.flags))
+            buffer.write(I32.pack(self.sequence_id))
+            buffer.write(U16.pack(len(header_bytes) // 4))
+            buffer.write(header_bytes)
+            buffer.write(payload)
+        elif self._client_type in (THeaderClientType.FRAMED_BINARY, THeaderClientType.FRAMED_COMPACT):
+            buffer.write(I32.pack(len(payload)))
+            buffer.write(payload)
+        elif self._client_type in (THeaderClientType.UNFRAMED_BINARY, THeaderClientType.UNFRAMED_COMPACT):
+            buffer.write(payload)
+        else:
+            raise TTransportException(
+                TTransportException.INVALID_CLIENT_TYPE,
+                "Unknown client type.",
+            )
+
+        # the frame length field doesn't count towards the frame payload size
+        frame_bytes = buffer.getvalue()
+        frame_payload_size = len(frame_bytes) - 4
+        if frame_payload_size > self._max_frame_size:
+            raise TTransportException(
+                TTransportException.SIZE_LIMIT,
+                "Attempting to send frame that is too large.",
+            )
+
+        self._transport.write(frame_bytes)
+        self._transport.flush()
+
+    @property
+    def cstringio_buf(self):
+        return self._read_buffer
+
+    def cstringio_refill(self, partialread, reqlen):
+        result = bytearray(partialread)
+        while len(result) < reqlen:
+            result += self.read(reqlen - len(result))
+        self._read_buffer = BufferIO(result)
+        return self._read_buffer
diff --git a/lib/py/src/transport/THttpClient.py b/lib/py/src/transport/THttpClient.py
index fb33421..37b0a4d 100644
--- a/lib/py/src/transport/THttpClient.py
+++ b/lib/py/src/transport/THttpClient.py
@@ -19,7 +19,7 @@
 
 from io import BytesIO
 import os
-import socket
+import ssl
 import sys
 import warnings
 import base64
@@ -34,17 +34,20 @@
 class THttpClient(TTransportBase):
     """Http implementation of TTransport base."""
 
-    def __init__(self, uri_or_host, port=None, path=None):
-        """THttpClient supports two different types constructor parameters.
+    def __init__(self, uri_or_host, port=None, path=None, cafile=None, cert_file=None, key_file=None, ssl_context=None):
+        """THttpClient supports two different types of construction:
 
         THttpClient(host, port, path) - deprecated
-        THttpClient(uri)
+        THttpClient(uri, [port=<n>, path=<s>, cafile=<filename>, cert_file=<filename>, key_file=<filename>, ssl_context=<context>])
 
-        Only the second supports https.
+        Only the second supports https.  To properly authenticate against the server,
+        provide the client's identity by specifying cert_file and key_file.  To properly
+        authenticate the server, specify either cafile or ssl_context with a CA defined.
+        NOTE: if both cafile and ssl_context are defined, ssl_context will override cafile.
         """
         if port is not None:
             warnings.warn(
-                "Please use the THttpClient('http://host:port/path') syntax",
+                "Please use the THttpClient('http{s}://host:port/path') constructor",
                 DeprecationWarning,
                 stacklevel=2)
             self.host = uri_or_host
@@ -60,6 +63,9 @@
                 self.port = parsed.port or http_client.HTTP_PORT
             elif self.scheme == 'https':
                 self.port = parsed.port or http_client.HTTPS_PORT
+                self.certfile = cert_file
+                self.keyfile = key_file
+                self.context = ssl.create_default_context(cafile=cafile) if (cafile and not ssl_context) else ssl_context
             self.host = parsed.hostname
             self.path = parsed.path
             if parsed.query:
@@ -100,12 +106,17 @@
 
     def open(self):
         if self.scheme == 'http':
-            self.__http = http_client.HTTPConnection(self.host, self.port)
+            self.__http = http_client.HTTPConnection(self.host, self.port,
+                                                     timeout=self.__timeout)
         elif self.scheme == 'https':
-            self.__http = http_client.HTTPSConnection(self.host, self.port)
-            if self.using_proxy():
-                self.__http.set_tunnel(self.realhost, self.realport,
-                                       {"Proxy-Authorization": self.proxy_auth})
+            self.__http = http_client.HTTPSConnection(self.host, self.port,
+                                                      key_file=self.keyfile,
+                                                      cert_file=self.certfile,
+                                                      timeout=self.__timeout,
+                                                      context=self.context)
+        if self.using_proxy():
+            self.__http.set_tunnel(self.realhost, self.realport,
+                                   {"Proxy-Authorization": self.proxy_auth})
 
     def close(self):
         self.__http.close()
@@ -116,9 +127,6 @@
         return self.__http is not None
 
     def setTimeout(self, ms):
-        if not hasattr(socket, 'getdefaulttimeout'):
-            raise NotImplementedError
-
         if ms is None:
             self.__timeout = None
         else:
@@ -133,17 +141,6 @@
     def write(self, buf):
         self.__wbuf.write(buf)
 
-    def __withTimeout(f):
-        def _f(*args, **kwargs):
-            orig_timeout = socket.getdefaulttimeout()
-            socket.setdefaulttimeout(args[0].__timeout)
-            try:
-                result = f(*args, **kwargs)
-            finally:
-                socket.setdefaulttimeout(orig_timeout)
-            return result
-        return _f
-
     def flush(self):
         if self.isOpen():
             self.close()
@@ -188,7 +185,3 @@
         self.code = self.__http_response.status
         self.message = self.__http_response.reason
         self.headers = self.__http_response.msg
-
-    # Decorate if we know how to timeout
-    if hasattr(socket, 'getdefaulttimeout'):
-        flush = __withTimeout(flush)
diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py
index f85778a..b54ca5d 100644
--- a/lib/py/src/transport/TSSLSocket.py
+++ b/lib/py/src/transport/TSSLSocket.py
@@ -368,7 +368,7 @@
         plain_client, addr = self.handle.accept()
         try:
             client = self._wrap_socket(plain_client)
-        except (ssl.SSLError, OSError):
+        except (ssl.SSLError, socket.error, OSError):
             logger.exception('Error while accepting from %s', addr)
             # failed handshake/ssl wrap, close socket to client
             plain_client.close()
diff --git a/lib/py/src/transport/TSocket.py b/lib/py/src/transport/TSocket.py
index c91de9d..a7d6617 100644
--- a/lib/py/src/transport/TSocket.py
+++ b/lib/py/src/transport/TSocket.py
@@ -159,6 +159,15 @@
         self._unix_socket = unix_socket
         self._socket_family = socket_family
         self.handle = None
+        self._backlog = 128
+
+    def setBacklog(self, backlog=None):
+        if not self.handle:
+            self._backlog = backlog
+        else:
+            # We cann't update backlog when it is already listening, since the
+            # handle has been created.
+            logger.warn('You have to set backlog before listen.')
 
     def listen(self):
         res0 = self._resolveAddr()
@@ -183,7 +192,7 @@
         if hasattr(self.handle, 'settimeout'):
             self.handle.settimeout(None)
         self.handle.bind(res[4])
-        self.handle.listen(128)
+        self.handle.listen(self._backlog)
 
     def accept(self):
         client, addr = self.handle.accept()
diff --git a/lib/py/src/transport/TTransport.py b/lib/py/src/transport/TTransport.py
index c8855ca..d13060f 100644
--- a/lib/py/src/transport/TTransport.py
+++ b/lib/py/src/transport/TTransport.py
@@ -32,6 +32,7 @@
     END_OF_FILE = 4
     NEGATIVE_SIZE = 5
     SIZE_LIMIT = 6
+    INVALID_CLIENT_TYPE = 7
 
     def __init__(self, type=UNKNOWN, message=None):
         TException.__init__(self, message)
diff --git a/lib/py/test/test_sslsocket.py b/lib/py/test/test_sslsocket.py
index 3c4be9c..f1344e5 100644
--- a/lib/py/test/test_sslsocket.py
+++ b/lib/py/test/test_sslsocket.py
@@ -42,7 +42,7 @@
 CLIENT_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.key')
 CLIENT_CA = os.path.join(ROOT_DIR, 'test', 'keys', 'CA.pem')
 
-TEST_CIPHERS = 'DES-CBC3-SHA'
+TEST_CIPHERS = 'DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256'
 
 
 class ServerAcceptor(threading.Thread):
@@ -95,6 +95,11 @@
         self._client_accepted.wait()
         return self._client
 
+    def close(self):
+        if self._client:
+            self._client.close()
+        self._server.close()
+
 
 # Python 2.6 compat
 class AssertRaises(object):
@@ -125,9 +130,7 @@
             client = TSSLSocket(host, port, unix_socket=path, **client_kwargs)
             yield acc, client
         finally:
-            if acc.client:
-                acc.client.close()
-            server.close()
+            acc.close()
 
     def _assert_connection_failure(self, server, path=None, **client_args):
         logging.disable(logging.CRITICAL)
diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile
index cdecaa6..5e5e5ac 100644
--- a/lib/rb/Rakefile
+++ b/lib/rb/Rakefile
@@ -71,6 +71,7 @@
 
 desc "Build the native library"
 task :build_ext => :'gen-rb' do
+   next if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
    Dir::chdir(File::dirname('ext/extconf.rb')) do
       unless sh "ruby #{File::basename('ext/extconf.rb')}"
         $stderr.puts "Failed to run extconf"
diff --git a/lib/rb/lib/thrift/protocol/base_protocol.rb b/lib/rb/lib/thrift/protocol/base_protocol.rb
index 88f44d4..5c693e9 100644
--- a/lib/rb/lib/thrift/protocol/base_protocol.rb
+++ b/lib/rb/lib/thrift/protocol/base_protocol.rb
@@ -369,11 +369,19 @@
         read_list_end
       end
     end
+    
+    def to_s
+      "#{trans.to_s}"
+    end
   end
 
   class BaseProtocolFactory
     def get_protocol(trans)
       raise NotImplementedError
     end
+    
+    def to_s
+      "base"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/protocol/binary_protocol.rb b/lib/rb/lib/thrift/protocol/binary_protocol.rb
index e70b1e3..d8279db 100644
--- a/lib/rb/lib/thrift/protocol/binary_protocol.rb
+++ b/lib/rb/lib/thrift/protocol/binary_protocol.rb
@@ -226,12 +226,19 @@
       size = read_i32
       trans.read_all(size)
     end
-
+    
+    def to_s
+      "binary(#{super.to_s})"
+    end
   end
 
   class BinaryProtocolFactory < BaseProtocolFactory
     def get_protocol(trans)
       return Thrift::BinaryProtocol.new(trans)
     end
+    
+    def to_s
+      "binary"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/protocol/binary_protocol_accelerated.rb b/lib/rb/lib/thrift/protocol/binary_protocol_accelerated.rb
index 70ea652..09b0264 100644
--- a/lib/rb/lib/thrift/protocol/binary_protocol_accelerated.rb
+++ b/lib/rb/lib/thrift/protocol/binary_protocol_accelerated.rb
@@ -35,5 +35,13 @@
         BinaryProtocol.new(trans)
       end
     end
+
+    def to_s
+      if (defined? BinaryProtocolAccelerated)
+        "binary-accel"
+      else
+        "binary"
+      end
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/protocol/compact_protocol.rb b/lib/rb/lib/thrift/protocol/compact_protocol.rb
index 605eea6..1f9bd30 100644
--- a/lib/rb/lib/thrift/protocol/compact_protocol.rb
+++ b/lib/rb/lib/thrift/protocol/compact_protocol.rb
@@ -345,6 +345,10 @@
       size = read_varint32()
       trans.read_all(size)
     end
+    
+    def to_s
+      "compact(#{super.to_s})"
+    end
 
     private
     
@@ -431,5 +435,9 @@
     def get_protocol(trans)
       CompactProtocol.new(trans)
     end
+    
+    def to_s
+      "compact"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/protocol/json_protocol.rb b/lib/rb/lib/thrift/protocol/json_protocol.rb
index 514bdbf..91e74e4 100644
--- a/lib/rb/lib/thrift/protocol/json_protocol.rb
+++ b/lib/rb/lib/thrift/protocol/json_protocol.rb
@@ -768,11 +768,19 @@
     def read_binary
       read_json_base64
     end
+
+    def to_s
+      "json(#{super.to_s})"
+    end
   end
 
   class JsonProtocolFactory < BaseProtocolFactory
     def get_protocol(trans)
       return Thrift::JsonProtocol.new(trans)
     end
+
+    def to_s
+      "json"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/protocol/multiplexed_protocol.rb b/lib/rb/lib/thrift/protocol/multiplexed_protocol.rb
index 13c9d93..b4428a7 100644
--- a/lib/rb/lib/thrift/protocol/multiplexed_protocol.rb
+++ b/lib/rb/lib/thrift/protocol/multiplexed_protocol.rb
@@ -36,5 +36,9 @@
         @protocol.write_message_begin(name, type, seqid)
       end 
     end
+    
+    def to_s
+      "multiplexed(#{@service_name=@protocol.to_s})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/server/base_server.rb b/lib/rb/lib/thrift/server/base_server.rb
index 1ee1213..aa4d09c 100644
--- a/lib/rb/lib/thrift/server/base_server.rb
+++ b/lib/rb/lib/thrift/server/base_server.rb
@@ -26,6 +26,12 @@
       @protocol_factory = protocol_factory ? protocol_factory : Thrift::BinaryProtocolFactory.new
     end
 
-    def serve; nil; end
+    def serve
+      raise NotImplementedError
+    end
+
+    def to_s
+      "server(#{@protocol_factory.to_s}(#{@transport_factory.to_s}(#{@server_transport.to_s})))"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/server/simple_server.rb b/lib/rb/lib/thrift/server/simple_server.rb
index 21e8659..905fe9b 100644
--- a/lib/rb/lib/thrift/server/simple_server.rb
+++ b/lib/rb/lib/thrift/server/simple_server.rb
@@ -39,5 +39,9 @@
         @server_transport.close
       end
     end
+    
+    def to_s
+      "simple(#{super.to_s})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/server/thread_pool_server.rb b/lib/rb/lib/thrift/server/thread_pool_server.rb
index 8cec805..bb754ad 100644
--- a/lib/rb/lib/thrift/server/thread_pool_server.rb
+++ b/lib/rb/lib/thrift/server/thread_pool_server.rb
@@ -71,5 +71,9 @@
         @server_transport.close
       end
     end
+    
+    def to_s
+      "threadpool(#{super.to_s})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/server/threaded_server.rb b/lib/rb/lib/thrift/server/threaded_server.rb
index a2c917c..88ee183 100644
--- a/lib/rb/lib/thrift/server/threaded_server.rb
+++ b/lib/rb/lib/thrift/server/threaded_server.rb
@@ -43,5 +43,9 @@
         @server_transport.close
       end
     end
+    
+    def to_s
+      "threaded(#{super.to_s})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/base_server_transport.rb b/lib/rb/lib/thrift/transport/base_server_transport.rb
index 68c5af0..0105463 100644
--- a/lib/rb/lib/thrift/transport/base_server_transport.rb
+++ b/lib/rb/lib/thrift/transport/base_server_transport.rb
@@ -34,4 +34,4 @@
       raise NotImplementedError
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/base_transport.rb b/lib/rb/lib/thrift/transport/base_transport.rb
index 8790326..97e5935 100644
--- a/lib/rb/lib/thrift/transport/base_transport.rb
+++ b/lib/rb/lib/thrift/transport/base_transport.rb
@@ -99,11 +99,19 @@
     alias_method :<<, :write
 
     def flush; end
+
+    def to_s
+      "base"
+    end
   end
   
   class BaseTransportFactory
     def get_transport(trans)
       return trans
     end
+    
+    def to_s
+      "base"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/buffered_transport.rb b/lib/rb/lib/thrift/transport/buffered_transport.rb
index 781d3c6..4fe9c41 100644
--- a/lib/rb/lib/thrift/transport/buffered_transport.rb
+++ b/lib/rb/lib/thrift/transport/buffered_transport.rb
@@ -104,11 +104,19 @@
       
       @transport.flush
     end
+
+    def to_s
+      "buffered(#{@transport.to_s})"
+    end
   end
 
   class BufferedTransportFactory < BaseTransportFactory
     def get_transport(transport)
       return BufferedTransport.new(transport)
     end
+    
+    def to_s
+      "buffered"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/framed_transport.rb b/lib/rb/lib/thrift/transport/framed_transport.rb
index d806ce0..9531778 100644
--- a/lib/rb/lib/thrift/transport/framed_transport.rb
+++ b/lib/rb/lib/thrift/transport/framed_transport.rb
@@ -99,6 +99,10 @@
       @wbuf = Bytes.empty_byte_buffer
     end
 
+    def to_s
+      "framed(#{@transport.to_s})"
+    end
+
     private
 
     def read_frame
@@ -113,5 +117,9 @@
     def get_transport(transport)
       return FramedTransport.new(transport)
     end
+    
+    def to_s
+      "framed"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/http_client_transport.rb b/lib/rb/lib/thrift/transport/http_client_transport.rb
index c9c4fec..5c1dd5c 100644
--- a/lib/rb/lib/thrift/transport/http_client_transport.rb
+++ b/lib/rb/lib/thrift/transport/http_client_transport.rb
@@ -53,5 +53,9 @@
     ensure
       @outbuf = Bytes.empty_byte_buffer
     end
+    
+    def to_s
+      "@{self.url}"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/io_stream_transport.rb b/lib/rb/lib/thrift/transport/io_stream_transport.rb
index e3c8379..ccec68f 100644
--- a/lib/rb/lib/thrift/transport/io_stream_transport.rb
+++ b/lib/rb/lib/thrift/transport/io_stream_transport.rb
@@ -35,5 +35,8 @@
     def write(buf); @output.write(Bytes.force_binary_encoding(buf)) end
     def close; @input.close; @output.close end
     def to_io; @input end # we're assuming this is used in a IO.select for reading
+    def to_s
+      "iostream(input=#{@input.to_s},output=#{@output.to_s})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/memory_buffer_transport.rb b/lib/rb/lib/thrift/transport/memory_buffer_transport.rb
index ad5ad85..469ea73 100644
--- a/lib/rb/lib/thrift/transport/memory_buffer_transport.rb
+++ b/lib/rb/lib/thrift/transport/memory_buffer_transport.rb
@@ -121,5 +121,9 @@
       end
       out.join(" ")
     end
+    
+    def to_s
+      "memory"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/server_socket.rb b/lib/rb/lib/thrift/transport/server_socket.rb
index 7feb9ab..5000232 100644
--- a/lib/rb/lib/thrift/transport/server_socket.rb
+++ b/lib/rb/lib/thrift/transport/server_socket.rb
@@ -59,5 +59,10 @@
     end
 
     alias to_io handle
+
+    def to_s
+      "socket(#{@host}:#{@port})"
+    end
+
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/socket.rb b/lib/rb/lib/thrift/transport/socket.rb
index 517d112..f5e6f3b 100644
--- a/lib/rb/lib/thrift/transport/socket.rb
+++ b/lib/rb/lib/thrift/transport/socket.rb
@@ -134,8 +134,10 @@
       @handle = nil
     end
 
-    def to_io
-      @handle
+    alias to_io handle
+
+    def to_s
+      "socket(#{@host}:#{@port})"
     end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/ssl_server_socket.rb b/lib/rb/lib/thrift/transport/ssl_server_socket.rb
index abc1343..3abd5ec 100644
--- a/lib/rb/lib/thrift/transport/ssl_server_socket.rb
+++ b/lib/rb/lib/thrift/transport/ssl_server_socket.rb
@@ -33,5 +33,9 @@
       socket = TCPServer.new(@host, @port)
       @handle = OpenSSL::SSL::SSLServer.new(socket, @ssl_context)
     end
+    
+    def to_s
+      "ssl(#{super.to_s})"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/ssl_socket.rb b/lib/rb/lib/thrift/transport/ssl_socket.rb
index dbbcc94..7ab96ab 100644
--- a/lib/rb/lib/thrift/transport/ssl_socket.rb
+++ b/lib/rb/lib/thrift/transport/ssl_socket.rb
@@ -43,5 +43,9 @@
         raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}")
       end
     end
+    
+    def to_s
+      "ssl(#{super.to_s})"
+    end
   end
 end
diff --git a/lib/rb/lib/thrift/transport/unix_server_socket.rb b/lib/rb/lib/thrift/transport/unix_server_socket.rb
index a135d25..057d122 100644
--- a/lib/rb/lib/thrift/transport/unix_server_socket.rb
+++ b/lib/rb/lib/thrift/transport/unix_server_socket.rb
@@ -56,5 +56,9 @@
     end
 
     alias to_io handle
+
+    def to_s
+      "domain(#{@path})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/lib/thrift/transport/unix_socket.rb b/lib/rb/lib/thrift/transport/unix_socket.rb
index 8f692e4..5dffd59 100644
--- a/lib/rb/lib/thrift/transport/unix_socket.rb
+++ b/lib/rb/lib/thrift/transport/unix_socket.rb
@@ -36,5 +36,9 @@
         raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}")
       end
     end
+    
+    def to_s
+      "domain(#{@path})"
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rb/spec/base_protocol_spec.rb b/lib/rb/spec/base_protocol_spec.rb
index ec50c48..eca936b 100644
--- a/lib/rb/spec/base_protocol_spec.rb
+++ b/lib/rb/spec/base_protocol_spec.rb
@@ -22,41 +22,46 @@
 describe 'BaseProtocol' do
 
   before(:each) do
-    @trans = mock("MockTransport")
+    @trans = double("MockTransport")
     @prot = Thrift::BaseProtocol.new(@trans)
   end
 
   describe Thrift::BaseProtocol do
     # most of the methods are stubs, so we can ignore them
 
+    it "should provide a reasonable to_s" do
+      expect(@trans).to receive(:to_s).once.and_return("trans")
+      expect(@prot.to_s).to eq("trans")
+    end
+
     it "should make trans accessible" do
-      @prot.trans.should eql(@trans)
+      expect(@prot.trans).to eql(@trans)
     end
 
     it 'should write out a field nicely (deprecated write_field signature)' do
-      @prot.should_receive(:write_field_begin).with('field', 'type', 'fid').ordered
-      @prot.should_receive(:write_type).with({:name => 'field', :type => 'type'}, 'value').ordered
-      @prot.should_receive(:write_field_end).ordered
+      expect(@prot).to receive(:write_field_begin).with('field', 'type', 'fid').ordered
+      expect(@prot).to receive(:write_type).with({:name => 'field', :type => 'type'}, 'value').ordered
+      expect(@prot).to receive(:write_field_end).ordered
       @prot.write_field('field', 'type', 'fid', 'value')
     end
 
     it 'should write out a field nicely' do
-      @prot.should_receive(:write_field_begin).with('field', 'type', 'fid').ordered
-      @prot.should_receive(:write_type).with({:name => 'field', :type => 'type', :binary => false}, 'value').ordered
-      @prot.should_receive(:write_field_end).ordered
+      expect(@prot).to receive(:write_field_begin).with('field', 'type', 'fid').ordered
+      expect(@prot).to receive(:write_type).with({:name => 'field', :type => 'type', :binary => false}, 'value').ordered
+      expect(@prot).to receive(:write_field_end).ordered
       @prot.write_field({:name => 'field', :type => 'type', :binary => false}, 'fid', 'value')
     end
 
     it 'should write out the different types (deprecated write_type signature)' do
-      @prot.should_receive(:write_bool).with('bool').ordered
-      @prot.should_receive(:write_byte).with('byte').ordered
-      @prot.should_receive(:write_double).with('double').ordered
-      @prot.should_receive(:write_i16).with('i16').ordered
-      @prot.should_receive(:write_i32).with('i32').ordered
-      @prot.should_receive(:write_i64).with('i64').ordered
-      @prot.should_receive(:write_string).with('string').ordered
-      struct = mock('Struct')
-      struct.should_receive(:write).with(@prot).ordered
+      expect(@prot).to receive(:write_bool).with('bool').ordered
+      expect(@prot).to receive(:write_byte).with('byte').ordered
+      expect(@prot).to receive(:write_double).with('double').ordered
+      expect(@prot).to receive(:write_i16).with('i16').ordered
+      expect(@prot).to receive(:write_i32).with('i32').ordered
+      expect(@prot).to receive(:write_i64).with('i64').ordered
+      expect(@prot).to receive(:write_string).with('string').ordered
+      struct = double('Struct')
+      expect(struct).to receive(:write).with(@prot).ordered
       @prot.write_type(Thrift::Types::BOOL, 'bool')
       @prot.write_type(Thrift::Types::BYTE, 'byte')
       @prot.write_type(Thrift::Types::DOUBLE, 'double')
@@ -72,16 +77,16 @@
     end
 
     it 'should write out the different types' do
-      @prot.should_receive(:write_bool).with('bool').ordered
-      @prot.should_receive(:write_byte).with('byte').ordered
-      @prot.should_receive(:write_double).with('double').ordered
-      @prot.should_receive(:write_i16).with('i16').ordered
-      @prot.should_receive(:write_i32).with('i32').ordered
-      @prot.should_receive(:write_i64).with('i64').ordered
-      @prot.should_receive(:write_string).with('string').ordered
-      @prot.should_receive(:write_binary).with('binary').ordered
-      struct = mock('Struct')
-      struct.should_receive(:write).with(@prot).ordered
+      expect(@prot).to receive(:write_bool).with('bool').ordered
+      expect(@prot).to receive(:write_byte).with('byte').ordered
+      expect(@prot).to receive(:write_double).with('double').ordered
+      expect(@prot).to receive(:write_i16).with('i16').ordered
+      expect(@prot).to receive(:write_i32).with('i32').ordered
+      expect(@prot).to receive(:write_i64).with('i64').ordered
+      expect(@prot).to receive(:write_string).with('string').ordered
+      expect(@prot).to receive(:write_binary).with('binary').ordered
+      struct = double('Struct')
+      expect(struct).to receive(:write).with(@prot).ordered
       @prot.write_type({:type => Thrift::Types::BOOL}, 'bool')
       @prot.write_type({:type => Thrift::Types::BYTE}, 'byte')
       @prot.write_type({:type => Thrift::Types::DOUBLE}, 'double')
@@ -98,13 +103,13 @@
     end
 
     it 'should read the different types (deprecated read_type signature)' do
-      @prot.should_receive(:read_bool).ordered
-      @prot.should_receive(:read_byte).ordered
-      @prot.should_receive(:read_i16).ordered
-      @prot.should_receive(:read_i32).ordered
-      @prot.should_receive(:read_i64).ordered
-      @prot.should_receive(:read_double).ordered
-      @prot.should_receive(:read_string).ordered
+      expect(@prot).to receive(:read_bool).ordered
+      expect(@prot).to receive(:read_byte).ordered
+      expect(@prot).to receive(:read_i16).ordered
+      expect(@prot).to receive(:read_i32).ordered
+      expect(@prot).to receive(:read_i64).ordered
+      expect(@prot).to receive(:read_double).ordered
+      expect(@prot).to receive(:read_string).ordered
       @prot.read_type(Thrift::Types::BOOL)
       @prot.read_type(Thrift::Types::BYTE)
       @prot.read_type(Thrift::Types::I16)
@@ -120,14 +125,14 @@
     end
 
     it 'should read the different types' do
-      @prot.should_receive(:read_bool).ordered
-      @prot.should_receive(:read_byte).ordered
-      @prot.should_receive(:read_i16).ordered
-      @prot.should_receive(:read_i32).ordered
-      @prot.should_receive(:read_i64).ordered
-      @prot.should_receive(:read_double).ordered
-      @prot.should_receive(:read_string).ordered
-      @prot.should_receive(:read_binary).ordered
+      expect(@prot).to receive(:read_bool).ordered
+      expect(@prot).to receive(:read_byte).ordered
+      expect(@prot).to receive(:read_i16).ordered
+      expect(@prot).to receive(:read_i32).ordered
+      expect(@prot).to receive(:read_i64).ordered
+      expect(@prot).to receive(:read_double).ordered
+      expect(@prot).to receive(:read_string).ordered
+      expect(@prot).to receive(:read_binary).ordered
       @prot.read_type({:type => Thrift::Types::BOOL})
       @prot.read_type({:type => Thrift::Types::BYTE})
       @prot.read_type({:type => Thrift::Types::I16})
@@ -144,13 +149,13 @@
     end
 
     it "should skip the basic types" do
-      @prot.should_receive(:read_bool).ordered
-      @prot.should_receive(:read_byte).ordered
-      @prot.should_receive(:read_i16).ordered
-      @prot.should_receive(:read_i32).ordered
-      @prot.should_receive(:read_i64).ordered
-      @prot.should_receive(:read_double).ordered
-      @prot.should_receive(:read_string).ordered
+      expect(@prot).to receive(:read_bool).ordered
+      expect(@prot).to receive(:read_byte).ordered
+      expect(@prot).to receive(:read_i16).ordered
+      expect(@prot).to receive(:read_i32).ordered
+      expect(@prot).to receive(:read_i64).ordered
+      expect(@prot).to receive(:read_double).ordered
+      expect(@prot).to receive(:read_string).ordered
       @prot.skip(Thrift::Types::BOOL)
       @prot.skip(Thrift::Types::BYTE)
       @prot.skip(Thrift::Types::I16)
@@ -163,47 +168,47 @@
 
     it "should skip structs" do
       real_skip = @prot.method(:skip)
-      @prot.should_receive(:read_struct_begin).ordered
-      @prot.should_receive(:read_field_begin).exactly(4).times.and_return(
+      expect(@prot).to receive(:read_struct_begin).ordered
+      expect(@prot).to receive(:read_field_begin).exactly(4).times.and_return(
         ['field 1', Thrift::Types::STRING, 1],
         ['field 2', Thrift::Types::I32, 2],
         ['field 3', Thrift::Types::MAP, 3],
         [nil, Thrift::Types::STOP, 0]
       )
-      @prot.should_receive(:read_field_end).exactly(3).times
-      @prot.should_receive(:read_string).exactly(3).times
-      @prot.should_receive(:read_i32).ordered
-      @prot.should_receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRING, 1])
+      expect(@prot).to receive(:read_field_end).exactly(3).times
+      expect(@prot).to receive(:read_string).exactly(3).times
+      expect(@prot).to receive(:read_i32).ordered
+      expect(@prot).to receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRING, 1])
       # @prot.should_receive(:read_string).exactly(2).times
-      @prot.should_receive(:read_map_end).ordered
-      @prot.should_receive(:read_struct_end).ordered
+      expect(@prot).to receive(:read_map_end).ordered
+      expect(@prot).to receive(:read_struct_end).ordered
       real_skip.call(Thrift::Types::STRUCT)
     end
 
     it "should skip maps" do
       real_skip = @prot.method(:skip)
-      @prot.should_receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRUCT, 1])
-      @prot.should_receive(:read_string).ordered
-      @prot.should_receive(:read_struct_begin).ordered.and_return(["some_struct"])
-      @prot.should_receive(:read_field_begin).ordered.and_return([nil, Thrift::Types::STOP, nil]);
-      @prot.should_receive(:read_struct_end).ordered
-      @prot.should_receive(:read_map_end).ordered
+      expect(@prot).to receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRUCT, 1])
+      expect(@prot).to receive(:read_string).ordered
+      expect(@prot).to receive(:read_struct_begin).ordered.and_return(["some_struct"])
+      expect(@prot).to receive(:read_field_begin).ordered.and_return([nil, Thrift::Types::STOP, nil]);
+      expect(@prot).to receive(:read_struct_end).ordered
+      expect(@prot).to receive(:read_map_end).ordered
       real_skip.call(Thrift::Types::MAP)
     end
 
     it "should skip sets" do
       real_skip = @prot.method(:skip)
-      @prot.should_receive(:read_set_begin).ordered.and_return([Thrift::Types::I64, 9])
-      @prot.should_receive(:read_i64).ordered.exactly(9).times
-      @prot.should_receive(:read_set_end)
+      expect(@prot).to receive(:read_set_begin).ordered.and_return([Thrift::Types::I64, 9])
+      expect(@prot).to receive(:read_i64).ordered.exactly(9).times
+      expect(@prot).to receive(:read_set_end)
       real_skip.call(Thrift::Types::SET)
     end
 
     it "should skip lists" do
       real_skip = @prot.method(:skip)
-      @prot.should_receive(:read_list_begin).ordered.and_return([Thrift::Types::DOUBLE, 11])
-      @prot.should_receive(:read_double).ordered.exactly(11).times
-      @prot.should_receive(:read_list_end)
+      expect(@prot).to receive(:read_list_begin).ordered.and_return([Thrift::Types::DOUBLE, 11])
+      expect(@prot).to receive(:read_double).ordered.exactly(11).times
+      expect(@prot).to receive(:read_list_end)
       real_skip.call(Thrift::Types::LIST)
     end
   end
@@ -211,7 +216,11 @@
   describe Thrift::BaseProtocolFactory do
     it "should raise NotImplementedError" do
       # returning nil since Protocol is just an abstract class
-      lambda {Thrift::BaseProtocolFactory.new.get_protocol(mock("MockTransport"))}.should raise_error(NotImplementedError)
+      expect {Thrift::BaseProtocolFactory.new.get_protocol(double("MockTransport"))}.to raise_error(NotImplementedError)
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(Thrift::BaseProtocolFactory.new.to_s).to eq("base")
     end
   end
 end
diff --git a/lib/rb/spec/base_transport_spec.rb b/lib/rb/spec/base_transport_spec.rb
index 4196572..d2f60aa 100644
--- a/lib/rb/spec/base_transport_spec.rb
+++ b/lib/rb/spec/base_transport_spec.rb
@@ -24,105 +24,119 @@
   describe Thrift::TransportException do
     it "should make type accessible" do
       exc = Thrift::TransportException.new(Thrift::TransportException::ALREADY_OPEN, "msg")
-      exc.type.should == Thrift::TransportException::ALREADY_OPEN
-      exc.message.should == "msg"
+      expect(exc.type).to eq(Thrift::TransportException::ALREADY_OPEN)
+      expect(exc.message).to eq("msg")
     end
   end
 
   describe Thrift::BaseTransport do
     it "should read the specified size" do
       transport = Thrift::BaseTransport.new
-      transport.should_receive(:read).with(40).ordered.and_return("10 letters")
-      transport.should_receive(:read).with(30).ordered.and_return("fifteen letters")
-      transport.should_receive(:read).with(15).ordered.and_return("more characters")
-      transport.read_all(40).should == "10 lettersfifteen lettersmore characters"
+      expect(transport).to receive(:read).with(40).ordered.and_return("10 letters")
+      expect(transport).to receive(:read).with(30).ordered.and_return("fifteen letters")
+      expect(transport).to receive(:read).with(15).ordered.and_return("more characters")
+      expect(transport.read_all(40)).to eq("10 lettersfifteen lettersmore characters")
     end
 
     it "should stub out the rest of the methods" do
       # can't test for stubbiness, so just make sure they're defined
       [:open?, :open, :close, :read, :write, :flush].each do |sym|
-        Thrift::BaseTransport.method_defined?(sym).should be_true
+        expect(Thrift::BaseTransport.method_defined?(sym)).to be_truthy
       end
     end
 
     it "should alias << to write" do
-      Thrift::BaseTransport.instance_method(:<<).should == Thrift::BaseTransport.instance_method(:write)
+      expect(Thrift::BaseTransport.instance_method(:<<)).to eq(Thrift::BaseTransport.instance_method(:write))
+    end
+    
+    it "should provide a reasonable to_s" do
+      expect(Thrift::BaseTransport.new.to_s).to eq("base")
     end
   end
 
   describe Thrift::BaseServerTransport do
     it "should stub out its methods" do
       [:listen, :accept, :close].each do |sym|
-        Thrift::BaseServerTransport.method_defined?(sym).should be_true
+        expect(Thrift::BaseServerTransport.method_defined?(sym)).to be_truthy
       end
     end
   end
 
   describe Thrift::BaseTransportFactory do
     it "should return the transport it's given" do
-      transport = mock("Transport")
-      Thrift::BaseTransportFactory.new.get_transport(transport).should eql(transport)
+      transport = double("Transport")
+      expect(Thrift::BaseTransportFactory.new.get_transport(transport)).to eql(transport)
+    end
+    
+    it "should provide a reasonable to_s" do
+      expect(Thrift::BaseTransportFactory.new.to_s).to eq("base")
     end
   end
 
   describe Thrift::BufferedTransport do
+    it "should provide a to_s that describes the encapsulation" do
+      trans = double("Transport")
+      expect(trans).to receive(:to_s).and_return("mock")
+      expect(Thrift::BufferedTransport.new(trans).to_s).to eq("buffered(mock)")
+    end
+
     it "should pass through everything but write/flush/read" do
-      trans = mock("Transport")
-      trans.should_receive(:open?).ordered.and_return("+ open?")
-      trans.should_receive(:open).ordered.and_return("+ open")
-      trans.should_receive(:flush).ordered # from the close
-      trans.should_receive(:close).ordered.and_return("+ close")
+      trans = double("Transport")
+      expect(trans).to receive(:open?).ordered.and_return("+ open?")
+      expect(trans).to receive(:open).ordered.and_return("+ open")
+      expect(trans).to receive(:flush).ordered # from the close
+      expect(trans).to receive(:close).ordered.and_return("+ close")
       btrans = Thrift::BufferedTransport.new(trans)
-      btrans.open?.should == "+ open?"
-      btrans.open.should == "+ open"
-      btrans.close.should == "+ close"
+      expect(btrans.open?).to eq("+ open?")
+      expect(btrans.open).to eq("+ open")
+      expect(btrans.close).to eq("+ close")
     end
 
     it "should buffer reads in chunks of #{Thrift::BufferedTransport::DEFAULT_BUFFER}" do
-      trans = mock("Transport")
-      trans.should_receive(:read).with(Thrift::BufferedTransport::DEFAULT_BUFFER).and_return("lorum ipsum dolor emet")
+      trans = double("Transport")
+      expect(trans).to receive(:read).with(Thrift::BufferedTransport::DEFAULT_BUFFER).and_return("lorum ipsum dolor emet")
       btrans = Thrift::BufferedTransport.new(trans)
-      btrans.read(6).should == "lorum "
-      btrans.read(6).should == "ipsum "
-      btrans.read(6).should == "dolor "
-      btrans.read(6).should == "emet"
+      expect(btrans.read(6)).to eq("lorum ")
+      expect(btrans.read(6)).to eq("ipsum ")
+      expect(btrans.read(6)).to eq("dolor ")
+      expect(btrans.read(6)).to eq("emet")
     end
 
     it "should buffer writes and send them on flush" do
-      trans = mock("Transport")
+      trans = double("Transport")
       btrans = Thrift::BufferedTransport.new(trans)
       btrans.write("one/")
       btrans.write("two/")
       btrans.write("three/")
-      trans.should_receive(:write).with("one/two/three/").ordered
-      trans.should_receive(:flush).ordered
+      expect(trans).to receive(:write).with("one/two/three/").ordered
+      expect(trans).to receive(:flush).ordered
       btrans.flush
     end
 
     it "should only send buffered data once" do
-      trans = mock("Transport")
+      trans = double("Transport")
       btrans = Thrift::BufferedTransport.new(trans)
       btrans.write("one/")
       btrans.write("two/")
       btrans.write("three/")
-      trans.should_receive(:write).with("one/two/three/")
-      trans.stub!(:flush)
+      expect(trans).to receive(:write).with("one/two/three/")
+      allow(trans).to receive(:flush)
       btrans.flush
       # Nothing to flush with no data
       btrans.flush
     end
 
     it "should flush on close" do
-      trans = mock("Transport")
-      trans.should_receive(:close)
+      trans = double("Transport")
+      expect(trans).to receive(:close)
       btrans = Thrift::BufferedTransport.new(trans)
-      btrans.should_receive(:flush)
+      expect(btrans).to receive(:flush)
       btrans.close
     end
 
     it "should not write to socket if there's no data" do
-      trans = mock("Transport")
-      trans.should_receive(:flush)
+      trans = double("Transport")
+      expect(trans).to receive(:flush)
       btrans = Thrift::BufferedTransport.new(trans)
       btrans.flush
     end
@@ -130,80 +144,90 @@
 
   describe Thrift::BufferedTransportFactory do
     it "should wrap the given transport in a BufferedTransport" do
-      trans = mock("Transport")
-      btrans = mock("BufferedTransport")
-      Thrift::BufferedTransport.should_receive(:new).with(trans).and_return(btrans)
-      Thrift::BufferedTransportFactory.new.get_transport(trans).should == btrans
+      trans = double("Transport")
+      btrans = double("BufferedTransport")
+      expect(Thrift::BufferedTransport).to receive(:new).with(trans).and_return(btrans)
+      expect(Thrift::BufferedTransportFactory.new.get_transport(trans)).to eq(btrans)
+    end
+    
+    it "should provide a reasonable to_s" do
+      expect(Thrift::BufferedTransportFactory.new.to_s).to eq("buffered")
     end
   end
 
   describe Thrift::FramedTransport do
     before(:each) do
-      @trans = mock("Transport")
+      @trans = double("Transport")
+    end
+
+    it "should provide a to_s that describes the encapsulation" do
+      trans = double("Transport")
+      expect(trans).to receive(:to_s).and_return("mock")
+      expect(Thrift::FramedTransport.new(trans).to_s).to eq("framed(mock)")
     end
 
     it "should pass through open?/open/close" do
       ftrans = Thrift::FramedTransport.new(@trans)
-      @trans.should_receive(:open?).ordered.and_return("+ open?")
-      @trans.should_receive(:open).ordered.and_return("+ open")
-      @trans.should_receive(:close).ordered.and_return("+ close")
-      ftrans.open?.should == "+ open?"
-      ftrans.open.should == "+ open"
-      ftrans.close.should == "+ close"
+      expect(@trans).to receive(:open?).ordered.and_return("+ open?")
+      expect(@trans).to receive(:open).ordered.and_return("+ open")
+      expect(@trans).to receive(:close).ordered.and_return("+ close")
+      expect(ftrans.open?).to eq("+ open?")
+      expect(ftrans.open).to eq("+ open")
+      expect(ftrans.close).to eq("+ close")
     end
 
     it "should pass through read when read is turned off" do
       ftrans = Thrift::FramedTransport.new(@trans, false, true)
-      @trans.should_receive(:read).with(17).ordered.and_return("+ read")
-      ftrans.read(17).should == "+ read"
+      expect(@trans).to receive(:read).with(17).ordered.and_return("+ read")
+      expect(ftrans.read(17)).to eq("+ read")
     end
 
     it "should pass through write/flush when write is turned off" do
       ftrans = Thrift::FramedTransport.new(@trans, true, false)
-      @trans.should_receive(:write).with("foo").ordered.and_return("+ write")
-      @trans.should_receive(:flush).ordered.and_return("+ flush")
-      ftrans.write("foo").should == "+ write"
-      ftrans.flush.should == "+ flush"
+      expect(@trans).to receive(:write).with("foo").ordered.and_return("+ write")
+      expect(@trans).to receive(:flush).ordered.and_return("+ flush")
+      expect(ftrans.write("foo")).to eq("+ write")
+      expect(ftrans.flush).to eq("+ flush")
     end
 
     it "should return a full frame if asked for >= the frame's length" do
       frame = "this is a frame"
-      @trans.should_receive(:read_all).with(4).and_return("\000\000\000\017")
-      @trans.should_receive(:read_all).with(frame.length).and_return(frame)
-      Thrift::FramedTransport.new(@trans).read(frame.length + 10).should == frame
+      expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017")
+      expect(@trans).to receive(:read_all).with(frame.length).and_return(frame)
+      expect(Thrift::FramedTransport.new(@trans).read(frame.length + 10)).to eq(frame)
     end
 
     it "should return slices of the frame when asked for < the frame's length" do
       frame = "this is a frame"
-      @trans.should_receive(:read_all).with(4).and_return("\000\000\000\017")
-      @trans.should_receive(:read_all).with(frame.length).and_return(frame)
+      expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017")
+      expect(@trans).to receive(:read_all).with(frame.length).and_return(frame)
       ftrans = Thrift::FramedTransport.new(@trans)
-      ftrans.read(4).should == "this"
-      ftrans.read(4).should == " is "
-      ftrans.read(16).should == "a frame"
+      expect(ftrans.read(4)).to eq("this")
+      expect(ftrans.read(4)).to eq(" is ")
+      expect(ftrans.read(16)).to eq("a frame")
     end
 
     it "should return nothing if asked for <= 0" do
-      Thrift::FramedTransport.new(@trans).read(-2).should == ""
+      expect(Thrift::FramedTransport.new(@trans).read(-2)).to eq("")
     end
 
     it "should pull a new frame when the first is exhausted" do
       frame = "this is a frame"
       frame2 = "yet another frame"
-      @trans.should_receive(:read_all).with(4).and_return("\000\000\000\017", "\000\000\000\021")
-      @trans.should_receive(:read_all).with(frame.length).and_return(frame)
-      @trans.should_receive(:read_all).with(frame2.length).and_return(frame2)
+      expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017", "\000\000\000\021")
+      expect(@trans).to receive(:read_all).with(frame.length).and_return(frame)
+      expect(@trans).to receive(:read_all).with(frame2.length).and_return(frame2)
       ftrans = Thrift::FramedTransport.new(@trans)
-      ftrans.read(4).should == "this"
-      ftrans.read(8).should == " is a fr"
-      ftrans.read(6).should == "ame"
-      ftrans.read(4).should == "yet "
-      ftrans.read(16).should == "another frame"
+      expect(ftrans.read(4)).to eq("this")
+      expect(ftrans.read(8)).to eq(" is a fr")
+      expect(ftrans.read(6)).to eq("ame")
+      expect(ftrans.read(4)).to eq("yet ")
+      expect(ftrans.read(16)).to eq("another frame")
     end
 
     it "should buffer writes" do
       ftrans = Thrift::FramedTransport.new(@trans)
-      @trans.should_not_receive(:write)
+      expect(@trans).not_to receive(:write)
       ftrans.write("foo")
       ftrans.write("bar")
       ftrans.write("this is a frame")
@@ -213,15 +237,15 @@
       ftrans = Thrift::FramedTransport.new(@trans)
       ftrans.write("foobar", 3)
       ftrans.write("barfoo", 1)
-      @trans.stub!(:flush)
-      @trans.should_receive(:write).with("\000\000\000\004foob")
+      allow(@trans).to receive(:flush)
+      expect(@trans).to receive(:write).with("\000\000\000\004foob")
       ftrans.flush
     end
 
     it "should flush frames with a 4-byte header" do
       ftrans = Thrift::FramedTransport.new(@trans)
-      @trans.should_receive(:write).with("\000\000\000\035one/two/three/this is a frame").ordered
-      @trans.should_receive(:flush).ordered
+      expect(@trans).to receive(:write).with("\000\000\000\035one/two/three/this is a frame").ordered
+      expect(@trans).to receive(:flush).ordered
       ftrans.write("one/")
       ftrans.write("two/")
       ftrans.write("three/")
@@ -231,22 +255,26 @@
 
     it "should not flush the same buffered data twice" do
       ftrans = Thrift::FramedTransport.new(@trans)
-      @trans.should_receive(:write).with("\000\000\000\007foo/bar")
-      @trans.stub!(:flush)
+      expect(@trans).to receive(:write).with("\000\000\000\007foo/bar")
+      allow(@trans).to receive(:flush)
       ftrans.write("foo")
       ftrans.write("/bar")
       ftrans.flush
-      @trans.should_receive(:write).with("\000\000\000\000")
+      expect(@trans).to receive(:write).with("\000\000\000\000")
       ftrans.flush
     end
   end
 
   describe Thrift::FramedTransportFactory do
     it "should wrap the given transport in a FramedTransport" do
-      trans = mock("Transport")
-      Thrift::FramedTransport.should_receive(:new).with(trans)
+      trans = double("Transport")
+      expect(Thrift::FramedTransport).to receive(:new).with(trans)
       Thrift::FramedTransportFactory.new.get_transport(trans)
     end
+    
+    it "should provide a reasonable to_s" do
+      expect(Thrift::FramedTransportFactory.new.to_s).to eq("framed")
+    end
   end
 
   describe Thrift::MemoryBufferTransport do
@@ -254,96 +282,106 @@
       @buffer = Thrift::MemoryBufferTransport.new
     end
 
+    it "should provide a reasonable to_s" do
+      expect(@buffer.to_s).to eq("memory")
+    end
+
     it "should accept a buffer on input and use it directly" do
       s = "this is a test"
       @buffer = Thrift::MemoryBufferTransport.new(s)
-      @buffer.read(4).should == "this"
+      expect(@buffer.read(4)).to eq("this")
       s.slice!(-4..-1)
-      @buffer.read(@buffer.available).should == " is a "
+      expect(@buffer.read(@buffer.available)).to eq(" is a ")
     end
 
     it "should always remain open" do
-      @buffer.should be_open
+      expect(@buffer).to be_open
       @buffer.close
-      @buffer.should be_open
+      expect(@buffer).to be_open
     end
 
     it "should respond to peek and available" do
       @buffer.write "some data"
-      @buffer.peek.should be_true
-      @buffer.available.should == 9
+      expect(@buffer.peek).to be_truthy
+      expect(@buffer.available).to eq(9)
       @buffer.read(4)
-      @buffer.peek.should be_true
-      @buffer.available.should == 5
+      expect(@buffer.peek).to be_truthy
+      expect(@buffer.available).to eq(5)
       @buffer.read(5)
-      @buffer.peek.should be_false
-      @buffer.available.should == 0
+      expect(@buffer.peek).to be_falsey
+      expect(@buffer.available).to eq(0)
     end
 
     it "should be able to reset the buffer" do
       @buffer.write "test data"
       @buffer.reset_buffer("foobar")
-      @buffer.available.should == 6
-      @buffer.read(@buffer.available).should == "foobar"
+      expect(@buffer.available).to eq(6)
+      expect(@buffer.read(@buffer.available)).to eq("foobar")
       @buffer.reset_buffer
-      @buffer.available.should == 0
+      expect(@buffer.available).to eq(0)
     end
 
     it "should copy the given string when resetting the buffer" do
       s = "this is a test"
       @buffer.reset_buffer(s)
-      @buffer.available.should == 14
+      expect(@buffer.available).to eq(14)
       @buffer.read(10)
-      @buffer.available.should == 4
-      s.should == "this is a test"
+      expect(@buffer.available).to eq(4)
+      expect(s).to eq("this is a test")
     end
 
     it "should return from read what was given in write" do
       @buffer.write "test data"
-      @buffer.read(4).should == "test"
-      @buffer.read(@buffer.available).should == " data"
+      expect(@buffer.read(4)).to eq("test")
+      expect(@buffer.read(@buffer.available)).to eq(" data")
       @buffer.write "foo"
       @buffer.write " bar"
-      @buffer.read(@buffer.available).should == "foo bar"
+      expect(@buffer.read(@buffer.available)).to eq("foo bar")
     end
 
     it "should throw an EOFError when there isn't enough data in the buffer" do
       @buffer.reset_buffer("")
-      lambda{@buffer.read(1)}.should raise_error(EOFError)
+      expect{@buffer.read(1)}.to raise_error(EOFError)
 
       @buffer.reset_buffer("1234")
-      lambda{@buffer.read(5)}.should raise_error(EOFError)
+      expect{@buffer.read(5)}.to raise_error(EOFError)
     end
   end
 
   describe Thrift::IOStreamTransport do
     before(:each) do
-      @input = mock("Input", :closed? => false)
-      @output = mock("Output", :closed? => false)
+      @input = double("Input", :closed? => false)
+      @output = double("Output", :closed? => false)
       @trans = Thrift::IOStreamTransport.new(@input, @output)
     end
 
+    it "should provide a reasonable to_s" do
+      expect(@input).to receive(:to_s).and_return("mock_input")
+      expect(@output).to receive(:to_s).and_return("mock_output")
+      expect(@trans.to_s).to eq("iostream(input=mock_input,output=mock_output)")
+    end
+
     it "should be open as long as both input or output are open" do
-      @trans.should be_open
-      @input.stub!(:closed?).and_return(true)
-      @trans.should be_open
-      @input.stub!(:closed?).and_return(false)
-      @output.stub!(:closed?).and_return(true)
-      @trans.should be_open
-      @input.stub!(:closed?).and_return(true)
-      @trans.should_not be_open
+      expect(@trans).to be_open
+      allow(@input).to receive(:closed?).and_return(true)
+      expect(@trans).to be_open
+      allow(@input).to receive(:closed?).and_return(false)
+      allow(@output).to receive(:closed?).and_return(true)
+      expect(@trans).to be_open
+      allow(@input).to receive(:closed?).and_return(true)
+      expect(@trans).not_to be_open
     end
 
     it "should pass through read/write to input/output" do
-      @input.should_receive(:read).with(17).and_return("+ read")
-      @output.should_receive(:write).with("foobar").and_return("+ write")
-      @trans.read(17).should == "+ read"
-      @trans.write("foobar").should == "+ write"
+      expect(@input).to receive(:read).with(17).and_return("+ read")
+      expect(@output).to receive(:write).with("foobar").and_return("+ write")
+      expect(@trans.read(17)).to eq("+ read")
+      expect(@trans.write("foobar")).to eq("+ write")
     end
 
     it "should close both input and output when closed" do
-      @input.should_receive(:close)
-      @output.should_receive(:close)
+      expect(@input).to receive(:close)
+      expect(@output).to receive(:close)
       @trans.close
     end
   end
diff --git a/lib/rb/spec/binary_protocol_accelerated_spec.rb b/lib/rb/spec/binary_protocol_accelerated_spec.rb
index bac9ea7..b2cd04b 100644
--- a/lib/rb/spec/binary_protocol_accelerated_spec.rb
+++ b/lib/rb/spec/binary_protocol_accelerated_spec.rb
@@ -33,10 +33,14 @@
 
     describe Thrift::BinaryProtocolAcceleratedFactory do
       it "should create a BinaryProtocolAccelerated" do
-        Thrift::BinaryProtocolAcceleratedFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(Thrift::BinaryProtocolAccelerated)
+        expect(Thrift::BinaryProtocolAcceleratedFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::BinaryProtocolAccelerated)
+      end
+
+      it "should provide a reasonable to_s" do
+        expect(Thrift::BinaryProtocolAcceleratedFactory.new.to_s).to eq("binary-accel")
       end
     end
   end
 else
   puts "skipping BinaryProtocolAccelerated spec because it is not defined."
-end
\ No newline at end of file
+end
diff --git a/lib/rb/spec/binary_protocol_spec.rb b/lib/rb/spec/binary_protocol_spec.rb
index 32772d3..065f5ce 100644
--- a/lib/rb/spec/binary_protocol_spec.rb
+++ b/lib/rb/spec/binary_protocol_spec.rb
@@ -38,29 +38,37 @@
     it "should read a message header" do
       @trans.write([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::REPLY].pack('N'))
       @trans.write([42].pack('N'))
-      @prot.should_receive(:read_string).and_return('testMessage')
-      @prot.read_message_begin.should == ['testMessage', Thrift::MessageTypes::REPLY, 42]
+      expect(@prot).to receive(:read_string).and_return('testMessage')
+      expect(@prot.read_message_begin).to eq(['testMessage', Thrift::MessageTypes::REPLY, 42])
     end
 
     it "should raise an exception if the message header has the wrong version" do
-      @prot.should_receive(:read_i32).and_return(-1)
-      lambda { @prot.read_message_begin }.should raise_error(Thrift::ProtocolException, 'Missing version identifier') do |e|
+      expect(@prot).to receive(:read_i32).and_return(-1)
+      expect { @prot.read_message_begin }.to raise_error(Thrift::ProtocolException, 'Missing version identifier') do |e|
         e.type == Thrift::ProtocolException::BAD_VERSION
       end
     end
 
     it "should raise an exception if the message header does not exist and strict_read is enabled" do
-      @prot.should_receive(:read_i32).and_return(42)
-      @prot.should_receive(:strict_read).and_return(true)
-      lambda { @prot.read_message_begin }.should raise_error(Thrift::ProtocolException, 'No version identifier, old protocol client?') do |e|
+      expect(@prot).to receive(:read_i32).and_return(42)
+      expect(@prot).to receive(:strict_read).and_return(true)
+      expect { @prot.read_message_begin }.to raise_error(Thrift::ProtocolException, 'No version identifier, old protocol client?') do |e|
         e.type == Thrift::ProtocolException::BAD_VERSION
       end
     end
+
+    it "should provide a reasonable to_s" do
+      expect(@prot.to_s).to eq("binary(memory)")
+    end
   end
 
   describe Thrift::BinaryProtocolFactory do
     it "should create a BinaryProtocol" do
-      Thrift::BinaryProtocolFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(Thrift::BinaryProtocol)
+      expect(Thrift::BinaryProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::BinaryProtocol)
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(Thrift::BinaryProtocolFactory.new.to_s).to eq("binary")
     end
   end
 end
diff --git a/lib/rb/spec/binary_protocol_spec_shared.rb b/lib/rb/spec/binary_protocol_spec_shared.rb
index 7a9d028..58d65f0 100644
--- a/lib/rb/spec/binary_protocol_spec_shared.rb
+++ b/lib/rb/spec/binary_protocol_spec_shared.rb
@@ -27,34 +27,34 @@
   end
 
   it "should define the proper VERSION_1, VERSION_MASK AND TYPE_MASK" do
-    protocol_class.const_get(:VERSION_MASK).should == 0xffff0000
-    protocol_class.const_get(:VERSION_1).should == 0x80010000
-    protocol_class.const_get(:TYPE_MASK).should == 0x000000ff
+    expect(protocol_class.const_get(:VERSION_MASK)).to eq(0xffff0000)
+    expect(protocol_class.const_get(:VERSION_1)).to eq(0x80010000)
+    expect(protocol_class.const_get(:TYPE_MASK)).to eq(0x000000ff)
   end
 
   it "should make strict_read readable" do
-    @prot.strict_read.should eql(true)
+    expect(@prot.strict_read).to eql(true)
   end
 
   it "should make strict_write readable" do
-    @prot.strict_write.should eql(true)
+    expect(@prot.strict_write).to eql(true)
   end    
 
   it "should write the message header" do
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
-    @trans.read(@trans.available).should == [protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N")
+    expect(@trans.read(@trans.available)).to eq([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N"))
   end
   
   it "should write the message header without version when writes are not strict" do
     @prot = protocol_class.new(@trans, true, false) # no strict write
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
-    @trans.read(@trans.available).should == "\000\000\000\vtestMessage\001\000\000\000\021"
+    expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021")
   end
   
   it "should write the message header with a version when writes are strict" do
     @prot = protocol_class.new(@trans) # strict write
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
-    @trans.read(@trans.available).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
+    expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021")
   end
   
 
@@ -62,64 +62,67 @@
 
   it "should write the field header" do
     @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3)
-    @trans.read(@trans.available).should == [Thrift::Types::DOUBLE, 3].pack("cn")
+    expect(@trans.read(@trans.available)).to eq([Thrift::Types::DOUBLE, 3].pack("cn"))
   end
   
   # field footer is a noop
   
   it "should write the STOP field" do
     @prot.write_field_stop
-    @trans.read(1).should == "\000"
+    expect(@trans.read(1)).to eq("\000")
   end
   
   it "should write the map header" do
     @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17)
-    @trans.read(@trans.available).should == [Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN");
+    expect(@trans.read(@trans.available)).to eq([Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN"));
   end
    
   # map footer is a noop
   
   it "should write the list header" do
     @prot.write_list_begin(Thrift::Types::I16, 42)
-    @trans.read(@trans.available).should == [Thrift::Types::I16, 42].pack("cN")
+    expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN"))
   end
   
   # list footer is a noop
   
   it "should write the set header" do
     @prot.write_set_begin(Thrift::Types::I16, 42)
-    @trans.read(@trans.available).should == [Thrift::Types::I16, 42].pack("cN")
+    expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN"))
   end
   
   it "should write a bool" do
     @prot.write_bool(true)
     @prot.write_bool(false)
-    @trans.read(@trans.available).should == "\001\000"
+    expect(@trans.read(@trans.available)).to eq("\001\000")
   end
   
   it "should treat a nil bool as false" do
     @prot.write_bool(nil)
-    @trans.read(1).should == "\000"
+    expect(@trans.read(1)).to eq("\000")
   end
   
   it "should write a byte" do
     # byte is small enough, let's check -128..127
     (-128..127).each do |i|
       @prot.write_byte(i)
-      @trans.read(1).should == [i].pack('c')
+      expect(@trans.read(1)).to eq([i].pack('c'))
     end
-    # handing it numbers out of signed range should clip
-    @trans.rspec_verify
+  end
+
+  it "should clip numbers out of signed range" do
     (128..255).each do |i|
       @prot.write_byte(i)
-      @trans.read(1).should == [i].pack('c')
+      expect(@trans.read(1)).to eq([i].pack('c'))
     end
-    # and lastly, a Bignum is going to error out
-    lambda { @prot.write_byte(2**65) }.should raise_error(RangeError)
+  end
+
+  it "errors out with a Bignum" do
+    expect { @prot.write_byte(2**65) }.to raise_error(RangeError)
   end
   
   it "should error gracefully when trying to write a nil byte" do
-    lambda { @prot.write_byte(nil) }.should raise_error
+    expect { @prot.write_byte(nil) }.to raise_error
   end
   
   it "should write an i16" do
@@ -131,14 +134,14 @@
     # and try something out of signed range, it should clip
     @prot.write_i16(2**15 + 5)
     
-    @trans.read(@trans.available).should == "\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005"
+    expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005")
     
     # a Bignum should error
     # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError)
   end
   
   it "should error gracefully when trying to write a nil i16" do
-    lambda { @prot.write_i16(nil) }.should raise_error
+    expect { @prot.write_i16(nil) }.to raise_error
   end
   
   it "should write an i32" do
@@ -148,14 +151,14 @@
       @prot.write_i32(i)
     end
     # try something out of signed range, it should clip
-    @trans.read(@trans.available).should == "\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377"
+    expect(@trans.read(@trans.available)).to eq("\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377")
     [2 ** 31 + 5, 2 ** 65 + 5].each do |i|
-      lambda { @prot.write_i32(i) }.should raise_error(RangeError)  
+      expect { @prot.write_i32(i) }.to raise_error(RangeError)  
     end
   end
   
   it "should error gracefully when trying to write a nil i32" do
-    lambda { @prot.write_i32(nil) }.should raise_error
+    expect { @prot.write_i32(nil) }.to raise_error
   end
   
   it "should write an i64" do
@@ -165,7 +168,7 @@
       @prot.write_i64(i)
     end
     # try something out of signed range, it should clip
-    @trans.read(@trans.available).should == ["\200\000\000\000\000\000\000\000",
+    expect(@trans.read(@trans.available)).to eq(["\200\000\000\000\000\000\000\000",
       "\377\377\364\303\035\244+]",
       "\377\377\377\377\376\231:\341",
       "\377\377\377\377\377\377\377\026",
@@ -173,12 +176,12 @@
       "\000\000\000\000\000\000\004\317",
       "\000\000\000\000\000#\340\204",
       "\000\000\000\002\340\311~\365",
-      "\177\377\377\377\377\377\377\377"].join("")
-    lambda { @prot.write_i64(2 ** 65 + 5) }.should raise_error(RangeError)
+      "\177\377\377\377\377\377\377\377"].join(""))
+    expect { @prot.write_i64(2 ** 65 + 5) }.to raise_error(RangeError)
   end
   
   it "should error gracefully when trying to write a nil i64" do
-    lambda { @prot.write_i64(nil) }.should raise_error
+    expect { @prot.write_i64(nil) }.to raise_error
   end
   
   it "should write a double" do
@@ -186,12 +189,12 @@
     values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
     values.each do |f|
       @prot.write_double(f)
-      @trans.read(@trans.available).should == [f].pack("G")
+      expect(@trans.read(@trans.available)).to eq([f].pack("G"))
     end
   end
   
   it "should error gracefully when trying to write a nil double" do
-    lambda { @prot.write_double(nil) }.should raise_error
+    expect { @prot.write_double(nil) }.to raise_error
   end
 
   if RUBY_VERSION >= '1.9'
@@ -199,111 +202,111 @@
       str = 'abc'
       @prot.write_string(str)
       a = @trans.read(@trans.available)
-      a.encoding.should == Encoding::BINARY
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63]
+      expect(a.encoding).to eq(Encoding::BINARY)
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63])
     end
 
     it 'should write a string with unicode characters' do
       str = "abc \u20AC \u20AD".encode('UTF-8')
       @prot.write_string(str)
       a = @trans.read(@trans.available)
-      a.encoding.should == Encoding::BINARY
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x0B, 0x61, 0x62, 0x63, 0x20,
-                                0xE2, 0x82, 0xAC, 0x20, 0xE2, 0x82, 0xAD]
+      expect(a.encoding).to eq(Encoding::BINARY)
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x0B, 0x61, 0x62, 0x63, 0x20,
+                                0xE2, 0x82, 0xAC, 0x20, 0xE2, 0x82, 0xAD])
     end
 
     it 'should write should write a string with unicode characters and transcoding' do
       str = "abc \u20AC".encode('ISO-8859-15')
       @prot.write_string(str)
       a = @trans.read(@trans.available)
-      a.encoding.should == Encoding::BINARY
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC]
+      expect(a.encoding).to eq(Encoding::BINARY)
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
     end
 
     it 'should write a binary string' do
       buffer = [0, 1, 2, 3].pack('C*')
       @prot.write_binary(buffer)
       a = @trans.read(@trans.available)
-      a.encoding.should == Encoding::BINARY
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03]
+      expect(a.encoding).to eq(Encoding::BINARY)
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
     end
   else
     it 'should write a string' do
       str = 'abc'
       @prot.write_string(str)
       a = @trans.read(@trans.available)
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63]
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63])
     end
 
     it 'should write a binary string' do
       buffer = [0, 1, 2, 3].pack('C*')
       @prot.write_binary(buffer)
       a = @trans.read(@trans.available)
-      a.unpack('C*').should == [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03]
+      expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
     end
   end
 
   it "should error gracefully when trying to write a nil string" do
-    lambda { @prot.write_string(nil) }.should raise_error
+    expect { @prot.write_string(nil) }.to raise_error
   end
   
   it "should write the message header without version when writes are not strict" do
     @prot = protocol_class.new(@trans, true, false) # no strict write
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
-    @trans.read(@trans.available).should == "\000\000\000\vtestMessage\001\000\000\000\021"
+    expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021")
   end
     
   it "should write the message header with a version when writes are strict" do
     @prot = protocol_class.new(@trans) # strict write
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
-    @trans.read(@trans.available).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
+    expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021")
   end
   
   # message footer is a noop
   
   it "should read a field header" do
     @trans.write([Thrift::Types::STRING, 3].pack("cn"))
-    @prot.read_field_begin.should == [nil, Thrift::Types::STRING, 3]
+    expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STRING, 3])
   end
   
   # field footer is a noop
   
   it "should read a stop field" do
     @trans.write([Thrift::Types::STOP].pack("c"));
-    @prot.read_field_begin.should == [nil, Thrift::Types::STOP, 0]
+    expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STOP, 0])
   end
 
   it "should read a map header" do
     @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN"))
-    @prot.read_map_begin.should == [Thrift::Types::DOUBLE, Thrift::Types::I64, 42]
+    expect(@prot.read_map_begin).to eq([Thrift::Types::DOUBLE, Thrift::Types::I64, 42])
   end
   
   # map footer is a noop
   
   it "should read a list header" do
     @trans.write([Thrift::Types::STRING, 17].pack("cN"))
-    @prot.read_list_begin.should == [Thrift::Types::STRING, 17]
+    expect(@prot.read_list_begin).to eq([Thrift::Types::STRING, 17])
   end
   
   # list footer is a noop
   
   it "should read a set header" do
     @trans.write([Thrift::Types::STRING, 17].pack("cN"))
-    @prot.read_set_begin.should == [Thrift::Types::STRING, 17]
+    expect(@prot.read_set_begin).to eq([Thrift::Types::STRING, 17])
   end
   
   # set footer is a noop
   
   it "should read a bool" do
     @trans.write("\001\000");
-    @prot.read_bool.should == true
-    @prot.read_bool.should == false
+    expect(@prot.read_bool).to eq(true)
+    expect(@prot.read_bool).to eq(false)
   end
   
   it "should read a byte" do
     [-128, -57, -3, 0, 17, 24, 127].each do |i|
       @trans.write([i].pack("c"))
-      @prot.read_byte.should == i
+      expect(@prot.read_byte).to eq(i)
     end
   end
   
@@ -311,7 +314,7 @@
     # try a scattering of values, including min/max
     [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i|
       @trans.write([i].pack("n"));
-      @prot.read_i16.should == i
+      expect(@prot.read_i16).to eq(i)
     end
   end
   
@@ -319,7 +322,7 @@
     # try a scattering of values, including min/max
     [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i|
       @trans.write([i].pack("N"))
-      @prot.read_i32.should == i
+      expect(@prot.read_i32).to eq(i)
     end
   end
   
@@ -327,7 +330,7 @@
     # try a scattering of values, including min/max
     [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i|
       @trans.write([i >> 32, i & 0xFFFFFFFF].pack("NN"))
-      @prot.read_i64.should == i
+      expect(@prot.read_i64).to eq(i)
     end
   end
   
@@ -335,7 +338,7 @@
     # try a random scattering of values, including min/max
     [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f|
       @trans.write([f].pack("G"));
-      @prot.read_double.should == f
+      expect(@prot.read_double).to eq(f)
     end
   end
 
@@ -345,8 +348,8 @@
       buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*')
       @trans.write(buffer)
       a = @prot.read_string
-      a.should == 'abc'.encode('UTF-8')
-      a.encoding.should == Encoding::UTF_8
+      expect(a).to eq('abc'.encode('UTF-8'))
+      expect(a.encoding).to eq(Encoding::UTF_8)
     end
 
     it 'should read a string containing unicode characters from UTF-8 encoded buffer' do
@@ -354,44 +357,44 @@
       buffer = [0x00, 0x00, 0x00, 0x03, 0xE2, 0x82, 0xAC].pack('C*')
       @trans.write(buffer)
       a = @prot.read_string
-      a.should == "\u20AC".encode('UTF-8')
-      a.encoding.should == Encoding::UTF_8
+      expect(a).to eq("\u20AC".encode('UTF-8'))
+      expect(a.encoding).to eq(Encoding::UTF_8)
     end
 
     it 'should read a binary string' do
       buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*')
       @trans.write(buffer)
       a = @prot.read_binary
-      a.should == [0x00, 0x01, 0x02, 0x03].pack('C*')
-      a.encoding.should == Encoding::BINARY
+      expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*'))
+      expect(a.encoding).to eq(Encoding::BINARY)
     end
   else
     it 'should read a string' do
       # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c'
       buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*')
       @trans.write(buffer)
-      @prot.read_string.should == 'abc'
+      expect(@prot.read_string).to eq('abc')
     end
 
     it 'should read a binary string' do
       buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*')
       @trans.write(buffer)
       a = @prot.read_binary
-      a.should == [0x00, 0x01, 0x02, 0x03].pack('C*')
+      expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*'))
     end
   end
 
   it "should perform a complete rpc with no args or return" do
     srv_test(
       proc {|client| client.send_voidMethod()},
-      proc {|client| client.recv_voidMethod.should == nil}
+      proc {|client| expect(client.recv_voidMethod).to eq(nil)}
     )
   end
 
   it "should perform a complete rpc with a primitive return type" do
     srv_test(
       proc {|client| client.send_primitiveMethod()},
-      proc {|client| client.recv_primitiveMethod.should == 1}
+      proc {|client| expect(client.recv_primitiveMethod).to eq(1)}
     )
   end
 
@@ -402,7 +405,7 @@
         result = client.recv_structMethod
         result.set_byte_map = nil
         result.map_byte_map = nil
-        result.should == Fixtures::COMPACT_PROTOCOL_TEST_STRUCT
+        expect(result).to eq(Fixtures::COMPACT_PROTOCOL_TEST_STRUCT)
       }
     )
   end
diff --git a/lib/rb/spec/bytes_spec.rb b/lib/rb/spec/bytes_spec.rb
index b82e304..2e8653c 100644
--- a/lib/rb/spec/bytes_spec.rb
+++ b/lib/rb/spec/bytes_spec.rb
@@ -25,33 +25,33 @@
     describe '.empty_byte_buffer' do
       it 'should create an empty buffer' do
         b = Thrift::Bytes.empty_byte_buffer
-        b.length.should == 0
-        b.encoding.should == Encoding::BINARY
+        expect(b.length).to eq(0)
+        expect(b.encoding).to eq(Encoding::BINARY)
       end
 
       it 'should create an empty buffer of given size' do
         b = Thrift::Bytes.empty_byte_buffer 2
-        b.length.should == 2
-        b.getbyte(0).should == 0
-        b.getbyte(1).should == 0
-        b.encoding.should == Encoding::BINARY
+        expect(b.length).to eq(2)
+        expect(b.getbyte(0)).to eq(0)
+        expect(b.getbyte(1)).to eq(0)
+        expect(b.encoding).to eq(Encoding::BINARY)
       end
     end
 
     describe '.force_binary_encoding' do
       it 'should change encoding' do
         e = 'STRING'.encode('UTF-8')
-        e.encoding.should_not == Encoding::BINARY
+        expect(e.encoding).not_to eq(Encoding::BINARY)
         a = Thrift::Bytes.force_binary_encoding e
-        a.encoding.should == Encoding::BINARY
+        expect(a.encoding).to eq(Encoding::BINARY)
       end
     end
 
     describe '.get_string_byte' do
       it 'should get the byte at index' do
         s = "\x41\x42"
-        Thrift::Bytes.get_string_byte(s, 0).should == 0x41
-        Thrift::Bytes.get_string_byte(s, 1).should == 0x42
+        expect(Thrift::Bytes.get_string_byte(s, 0)).to eq(0x41)
+        expect(Thrift::Bytes.get_string_byte(s, 1)).to eq(0x42)
       end
     end
 
@@ -59,42 +59,42 @@
       it 'should set byte value at index' do
         s = "\x41\x42"
         Thrift::Bytes.set_string_byte(s, 0, 0x43)
-        s.getbyte(0).should == 0x43
-        s.should == 'CB'
+        expect(s.getbyte(0)).to eq(0x43)
+        expect(s).to eq('CB')
       end
     end
 
     describe '.convert_to_utf8_byte_buffer' do
       it 'should convert UTF-8 String to byte buffer' do
         e = "\u20AC".encode('UTF-8') # a string with euro sign character U+20AC
-        e.length.should == 1
+        expect(e.length).to eq(1)
 
         a = Thrift::Bytes.convert_to_utf8_byte_buffer e
-        a.encoding.should == Encoding::BINARY
-        a.length.should == 3
-        a.unpack('C*').should == [0xE2, 0x82, 0xAC]
+        expect(a.encoding).to eq(Encoding::BINARY)
+        expect(a.length).to eq(3)
+        expect(a.unpack('C*')).to eq([0xE2, 0x82, 0xAC])
       end
 
       it 'should convert ISO-8859-15 String to UTF-8 byte buffer' do
         # Assumptions
         e = "\u20AC".encode('ISO-8859-15') # a string with euro sign character U+20AC, then converted to ISO-8859-15
-        e.length.should == 1
-        e.unpack('C*').should == [0xA4] # euro sign is a different code point in ISO-8859-15
+        expect(e.length).to eq(1)
+        expect(e.unpack('C*')).to eq([0xA4]) # euro sign is a different code point in ISO-8859-15
 
         a = Thrift::Bytes.convert_to_utf8_byte_buffer e
-        a.encoding.should == Encoding::BINARY
-        a.length.should == 3
-        a.unpack('C*').should == [0xE2, 0x82, 0xAC]
+        expect(a.encoding).to eq(Encoding::BINARY)
+        expect(a.length).to eq(3)
+        expect(a.unpack('C*')).to eq([0xE2, 0x82, 0xAC])
       end
     end
 
     describe '.convert_to_string' do
       it 'should convert UTF-8 byte buffer to a UTF-8 String' do
         e = [0xE2, 0x82, 0xAC].pack("C*")
-        e.encoding.should == Encoding::BINARY
+        expect(e.encoding).to eq(Encoding::BINARY)
         a = Thrift::Bytes.convert_to_string e
-        a.encoding.should == Encoding::UTF_8
-        a.should == "\u20AC"
+        expect(a.encoding).to eq(Encoding::UTF_8)
+        expect(a).to eq("\u20AC")
       end
     end
 
@@ -102,14 +102,14 @@
     describe '.empty_byte_buffer' do
       it 'should create an empty buffer' do
         b = Thrift::Bytes.empty_byte_buffer
-        b.length.should == 0
+        expect(b.length).to eq(0)
       end
 
       it 'should create an empty buffer of given size' do
         b = Thrift::Bytes.empty_byte_buffer 2
-        b.length.should == 2
-        b[0].should == 0
-        b[1].should == 0
+        expect(b.length).to eq(2)
+        expect(b[0]).to eq(0)
+        expect(b[1]).to eq(0)
       end
     end
 
@@ -117,16 +117,16 @@
       it 'should be a no-op' do
         e = 'STRING'
         a = Thrift::Bytes.force_binary_encoding e
-        a.should == e
-        a.should be(e)
+        expect(a).to eq(e)
+        expect(a).to be(e)
       end
     end
 
     describe '.get_string_byte' do
       it 'should get the byte at index' do
         s = "\x41\x42"
-        Thrift::Bytes.get_string_byte(s, 0).should == 0x41
-        Thrift::Bytes.get_string_byte(s, 1).should == 0x42
+        expect(Thrift::Bytes.get_string_byte(s, 0)).to eq(0x41)
+        expect(Thrift::Bytes.get_string_byte(s, 1)).to eq(0x42)
       end
     end
 
@@ -134,8 +134,8 @@
       it 'should set byte value at index' do
         s = "\x41\x42"
         Thrift::Bytes.set_string_byte(s, 0, 0x43)
-        s[0].should == 0x43
-        s.should == 'CB'
+        expect(s[0]).to eq(0x43)
+        expect(s).to eq('CB')
       end
     end
 
@@ -143,8 +143,8 @@
       it 'should be a no-op' do
         e = 'STRING'
         a = Thrift::Bytes.convert_to_utf8_byte_buffer e
-        a.should == e
-        a.should be(e)
+        expect(a).to eq(e)
+        expect(a).to be(e)
       end
     end
 
@@ -152,8 +152,8 @@
       it 'should be a no-op' do
         e = 'STRING'
         a = Thrift::Bytes.convert_to_string e
-        a.should == e
-        a.should be(e)
+        expect(a).to eq(e)
+        expect(a).to be(e)
       end
     end
   end
diff --git a/lib/rb/spec/client_spec.rb b/lib/rb/spec/client_spec.rb
index f8ffe8a..d5d4cee 100644
--- a/lib/rb/spec/client_spec.rb
+++ b/lib/rb/spec/client_spec.rb
@@ -26,74 +26,73 @@
   end
 
   before(:each) do
-    @prot = mock("MockProtocol")
+    @prot = double("MockProtocol")
     @client = ClientSpec.new(@prot)
   end
 
   describe Thrift::Client do
     it "should re-use iprot for oprot if not otherwise specified" do
-      @client.instance_variable_get(:'@iprot').should eql(@prot)
-      @client.instance_variable_get(:'@oprot').should eql(@prot)
+      expect(@client.instance_variable_get(:'@iprot')).to eql(@prot)
+      expect(@client.instance_variable_get(:'@oprot')).to eql(@prot)
     end
 
     it "should send a test message" do
-      @prot.should_receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0)
-      mock_args = mock('#<TestMessage_args:mock>')
-      mock_args.should_receive(:foo=).with('foo')
-      mock_args.should_receive(:bar=).with(42)
-      mock_args.should_receive(:write).with(@prot)
-      @prot.should_receive(:write_message_end)
-      @prot.should_receive(:trans) do
-        mock('trans').tap do |trans|
-          trans.should_receive(:flush)
+      expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0)
+      mock_args = double('#<TestMessage_args:mock>')
+      expect(mock_args).to receive(:foo=).with('foo')
+      expect(mock_args).to receive(:bar=).with(42)
+      expect(mock_args).to receive(:write).with(@prot)
+      expect(@prot).to receive(:write_message_end)
+      expect(@prot).to receive(:trans) do
+        double('trans').tap do |trans|
+          expect(trans).to receive(:flush)
         end
       end
-      klass = stub("TestMessage_args", :new => mock_args)
+      klass = double("TestMessage_args", :new => mock_args)
       @client.send_message('testMessage', klass, :foo => 'foo', :bar => 42)
     end
 
     it "should increment the sequence id when sending messages" do
-      pending "it seems sequence ids are completely ignored right now" do
-        @prot.should_receive(:write_message_begin).with('testMessage',  Thrift::MessageTypes::CALL, 0).ordered
-        @prot.should_receive(:write_message_begin).with('testMessage2', Thrift::MessageTypes::CALL, 1).ordered
-        @prot.should_receive(:write_message_begin).with('testMessage3', Thrift::MessageTypes::CALL, 2).ordered
-        @prot.stub!(:write_message_end)
-        @prot.stub!(:trans).and_return mock("trans").as_null_object
-        @client.send_message('testMessage', mock("args class").as_null_object)
-        @client.send_message('testMessage2', mock("args class").as_null_object)
-        @client.send_message('testMessage3', mock("args class").as_null_object)
-      end
+      pending "it seems sequence ids are completely ignored right now"
+      @prot.expect(:write_message_begin).with('testMessage',  Thrift::MessageTypes::CALL, 0).ordered
+      @prot.expect(:write_message_begin).with('testMessage2', Thrift::MessageTypes::CALL, 1).ordered
+      @prot.expect(:write_message_begin).with('testMessage3', Thrift::MessageTypes::CALL, 2).ordered
+      @prot.stub!(:write_message_end)
+      @prot.stub!(:trans).and_return double("trans").as_null_object
+      @client.send_message('testMessage', double("args class").as_null_object)
+      @client.send_message('testMessage2', double("args class").as_null_object)
+      @client.send_message('testMessage3', double("args class").as_null_object)
     end
 
     it "should receive a test message" do
-      @prot.should_receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::CALL, 0]
-      @prot.should_receive(:read_message_end)
-      mock_klass = mock("#<MockClass:mock>")
-      mock_klass.should_receive(:read).with(@prot)
-      @client.receive_message(stub("MockClass", :new => mock_klass))
+      expect(@prot).to receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::CALL, 0]
+      expect(@prot).to receive(:read_message_end)
+      mock_klass = double("#<MockClass:mock>")
+      expect(mock_klass).to receive(:read).with(@prot)
+      @client.receive_message(double("MockClass", :new => mock_klass))
     end
 
     it "should handle received exceptions" do
-      @prot.should_receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::EXCEPTION, 0]
-      @prot.should_receive(:read_message_end)
-      Thrift::ApplicationException.should_receive(:new).and_return do
+      expect(@prot).to receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::EXCEPTION, 0]
+      expect(@prot).to receive(:read_message_end)
+      expect(Thrift::ApplicationException).to receive(:new) do
         StandardError.new.tap do |mock_exc|
-          mock_exc.should_receive(:read).with(@prot)
+          expect(mock_exc).to receive(:read).with(@prot)
         end
       end
-      lambda { @client.receive_message(nil) }.should raise_error(StandardError)
+      expect { @client.receive_message(nil) }.to raise_error(StandardError)
     end
 
     it "should close the transport if an error occurs while sending a message" do
-      @prot.stub!(:write_message_begin)
-      @prot.should_not_receive(:write_message_end)
-      mock_args = mock("#<TestMessage_args:mock>")
-      mock_args.should_receive(:write).with(@prot).and_raise(StandardError)
-      trans = mock("MockTransport")
-      @prot.stub!(:trans).and_return(trans)
-      trans.should_receive(:close)
-      klass = mock("TestMessage_args", :new => mock_args)
-      lambda { @client.send_message("testMessage", klass) }.should raise_error(StandardError)
+      allow(@prot).to receive(:write_message_begin)
+      expect(@prot).not_to receive(:write_message_end)
+      mock_args = double("#<TestMessage_args:mock>")
+      expect(mock_args).to receive(:write).with(@prot).and_raise(StandardError)
+      trans = double("MockTransport")
+      allow(@prot).to receive(:trans).and_return(trans)
+      expect(trans).to receive(:close)
+      klass = double("TestMessage_args", :new => mock_args)
+      expect { @client.send_message("testMessage", klass) }.to raise_error(StandardError)
     end
   end
 end
diff --git a/lib/rb/spec/compact_protocol_spec.rb b/lib/rb/spec/compact_protocol_spec.rb
index 8a1a228..513dd69 100644
--- a/lib/rb/spec/compact_protocol_spec.rb
+++ b/lib/rb/spec/compact_protocol_spec.rb
@@ -42,7 +42,7 @@
         proto.send(writer(primitive_type), value)
         # puts "buf: #{trans.inspect_buffer}" if primitive_type == :i64
         read_back = proto.send(reader(primitive_type))
-        read_back.should == value
+        expect(read_back).to eq(value)
       end
     end
   end
@@ -62,10 +62,10 @@
 
         proto = Thrift::CompactProtocol.new(trans)
         name, type, id = proto.read_field_begin
-        type.should == thrift_type
-        id.should == 15
+        expect(type).to eq(thrift_type)
+        expect(id).to eq(15)
         read_back = proto.send(reader(primitive_type))
-        read_back.should == value
+        expect(read_back).to eq(value)
         proto.read_field_end
       end
     end
@@ -81,7 +81,7 @@
 
     struct2 = Thrift::Test::CompactProtoTestStruct.new
     struct2.read(proto)    
-    struct2.should == struct
+    expect(struct2).to eq(struct)
   end
 
   it "should make method calls correctly" do
@@ -97,7 +97,7 @@
     client.send_Janky(1)
     # puts client_out_trans.inspect_buffer
     processor.process(client_out_proto, client_in_proto)
-    client.recv_Janky.should == 2
+    expect(client.recv_Janky).to eq(2)
   end
   
   it "should deal with fields following fields that have non-delta ids" do
@@ -113,7 +113,7 @@
     deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
     brcp2 = Thrift::Test::BreaksRubyCompactProtocol.new
     deser.deserialize(brcp2, bytes)
-    brcp2.should == brcp
+    expect(brcp2).to eq(brcp)
   end
   
   it "should deserialize an empty map to an empty hash" do
@@ -124,7 +124,12 @@
     deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
     struct2 = Thrift::Test::SingleMapTestStruct.new
     deser.deserialize(struct2, bytes)
-    struct.should == struct2
+    expect(struct).to eq(struct2)
+  end
+  
+  it "should provide a reasonable to_s" do
+    trans = Thrift::MemoryBufferTransport.new
+    expect(Thrift::CompactProtocol.new(trans).to_s).to eq("compact(memory)")
   end
   
   class JankyHandler
@@ -141,3 +146,13 @@
     "read_#{sym.to_s}"
   end
 end
+
+describe Thrift::CompactProtocolFactory do
+  it "should create a CompactProtocol" do
+    expect(Thrift::CompactProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::CompactProtocol)
+  end
+
+  it "should provide a reasonable to_s" do
+    expect(Thrift::CompactProtocolFactory.new.to_s).to eq("compact")
+  end
+end
diff --git a/lib/rb/spec/exception_spec.rb b/lib/rb/spec/exception_spec.rb
index d1da621..379ae69 100644
--- a/lib/rb/spec/exception_spec.rb
+++ b/lib/rb/spec/exception_spec.rb
@@ -24,107 +24,107 @@
   describe Thrift::Exception do
     it "should have an accessible message" do
       e = Thrift::Exception.new("test message")
-      e.message.should == "test message"
+      expect(e.message).to eq("test message")
     end
   end
 
   describe Thrift::ApplicationException do
     it "should inherit from Thrift::Exception" do
-      Thrift::ApplicationException.superclass.should == Thrift::Exception
+      expect(Thrift::ApplicationException.superclass).to eq(Thrift::Exception)
     end
 
     it "should have an accessible type and message" do
       e = Thrift::ApplicationException.new
-      e.type.should == Thrift::ApplicationException::UNKNOWN
-      e.message.should be_nil
+      expect(e.type).to eq(Thrift::ApplicationException::UNKNOWN)
+      expect(e.message).to be_nil
       e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message")
-      e.type.should == Thrift::ApplicationException::UNKNOWN_METHOD
-      e.message.should == "test message"
+      expect(e.type).to eq(Thrift::ApplicationException::UNKNOWN_METHOD)
+      expect(e.message).to eq("test message")
     end
 
     it "should read a struct off of a protocol" do
-      prot = mock("MockProtocol")
-      prot.should_receive(:read_struct_begin).ordered
-      prot.should_receive(:read_field_begin).exactly(3).times.and_return(
+      prot = double("MockProtocol")
+      expect(prot).to receive(:read_struct_begin).ordered
+      expect(prot).to receive(:read_field_begin).exactly(3).times.and_return(
         ["message", Thrift::Types::STRING, 1],
         ["type", Thrift::Types::I32, 2],
         [nil, Thrift::Types::STOP, 0]
       )
-      prot.should_receive(:read_string).ordered.and_return "test message"
-      prot.should_receive(:read_i32).ordered.and_return Thrift::ApplicationException::BAD_SEQUENCE_ID
-      prot.should_receive(:read_field_end).exactly(2).times
-      prot.should_receive(:read_struct_end).ordered
+      expect(prot).to receive(:read_string).ordered.and_return "test message"
+      expect(prot).to receive(:read_i32).ordered.and_return Thrift::ApplicationException::BAD_SEQUENCE_ID
+      expect(prot).to receive(:read_field_end).exactly(2).times
+      expect(prot).to receive(:read_struct_end).ordered
 
       e = Thrift::ApplicationException.new
       e.read(prot)
-      e.message.should == "test message"
-      e.type.should == Thrift::ApplicationException::BAD_SEQUENCE_ID
+      expect(e.message).to eq("test message")
+      expect(e.type).to eq(Thrift::ApplicationException::BAD_SEQUENCE_ID)
     end
 
     it "should skip bad fields when reading a struct" do
-      prot = mock("MockProtocol")
-      prot.should_receive(:read_struct_begin).ordered
-      prot.should_receive(:read_field_begin).exactly(5).times.and_return(
+      prot = double("MockProtocol")
+      expect(prot).to receive(:read_struct_begin).ordered
+      expect(prot).to receive(:read_field_begin).exactly(5).times.and_return(
         ["type", Thrift::Types::I32, 2],
         ["type", Thrift::Types::STRING, 2],
         ["message", Thrift::Types::MAP, 1],
         ["message", Thrift::Types::STRING, 3],
         [nil, Thrift::Types::STOP, 0]
       )
-      prot.should_receive(:read_i32).and_return Thrift::ApplicationException::INVALID_MESSAGE_TYPE
-      prot.should_receive(:skip).with(Thrift::Types::STRING).twice
-      prot.should_receive(:skip).with(Thrift::Types::MAP)
-      prot.should_receive(:read_field_end).exactly(4).times
-      prot.should_receive(:read_struct_end).ordered
+      expect(prot).to receive(:read_i32).and_return Thrift::ApplicationException::INVALID_MESSAGE_TYPE
+      expect(prot).to receive(:skip).with(Thrift::Types::STRING).twice
+      expect(prot).to receive(:skip).with(Thrift::Types::MAP)
+      expect(prot).to receive(:read_field_end).exactly(4).times
+      expect(prot).to receive(:read_struct_end).ordered
 
       e = Thrift::ApplicationException.new
       e.read(prot)
-      e.message.should be_nil
-      e.type.should == Thrift::ApplicationException::INVALID_MESSAGE_TYPE
+      expect(e.message).to be_nil
+      expect(e.type).to eq(Thrift::ApplicationException::INVALID_MESSAGE_TYPE)
     end
 
     it "should write a Thrift::ApplicationException struct to the oprot" do
-      prot = mock("MockProtocol")
-      prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
-      prot.should_receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
-      prot.should_receive(:write_string).with("test message").ordered
-      prot.should_receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
-      prot.should_receive(:write_i32).with(Thrift::ApplicationException::UNKNOWN_METHOD).ordered
-      prot.should_receive(:write_field_end).twice
-      prot.should_receive(:write_field_stop).ordered
-      prot.should_receive(:write_struct_end).ordered
+      prot = double("MockProtocol")
+      expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
+      expect(prot).to receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
+      expect(prot).to receive(:write_string).with("test message").ordered
+      expect(prot).to receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
+      expect(prot).to receive(:write_i32).with(Thrift::ApplicationException::UNKNOWN_METHOD).ordered
+      expect(prot).to receive(:write_field_end).twice
+      expect(prot).to receive(:write_field_stop).ordered
+      expect(prot).to receive(:write_struct_end).ordered
 
       e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message")
       e.write(prot)
     end
 
     it "should skip nil fields when writing to the oprot" do
-      prot = mock("MockProtocol")
-      prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
-      prot.should_receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
-      prot.should_receive(:write_string).with("test message").ordered
-      prot.should_receive(:write_field_end).ordered
-      prot.should_receive(:write_field_stop).ordered
-      prot.should_receive(:write_struct_end).ordered
+      prot = double("MockProtocol")
+      expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
+      expect(prot).to receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
+      expect(prot).to receive(:write_string).with("test message").ordered
+      expect(prot).to receive(:write_field_end).ordered
+      expect(prot).to receive(:write_field_stop).ordered
+      expect(prot).to receive(:write_struct_end).ordered
 
       e = Thrift::ApplicationException.new(nil, "test message")
       e.write(prot)
 
-      prot = mock("MockProtocol")
-      prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
-      prot.should_receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
-      prot.should_receive(:write_i32).with(Thrift::ApplicationException::BAD_SEQUENCE_ID).ordered
-      prot.should_receive(:write_field_end).ordered
-      prot.should_receive(:write_field_stop).ordered
-      prot.should_receive(:write_struct_end).ordered
+      prot = double("MockProtocol")
+      expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
+      expect(prot).to receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
+      expect(prot).to receive(:write_i32).with(Thrift::ApplicationException::BAD_SEQUENCE_ID).ordered
+      expect(prot).to receive(:write_field_end).ordered
+      expect(prot).to receive(:write_field_stop).ordered
+      expect(prot).to receive(:write_struct_end).ordered
 
       e = Thrift::ApplicationException.new(Thrift::ApplicationException::BAD_SEQUENCE_ID)
       e.write(prot)
 
-      prot = mock("MockProtocol")
-      prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
-      prot.should_receive(:write_field_stop).ordered
-      prot.should_receive(:write_struct_end).ordered
+      prot = double("MockProtocol")
+      expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
+      expect(prot).to receive(:write_field_stop).ordered
+      expect(prot).to receive(:write_struct_end).ordered
 
       e = Thrift::ApplicationException.new(nil)
       e.write(prot)
@@ -134,8 +134,8 @@
   describe Thrift::ProtocolException do
     it "should have an accessible type" do
       prot = Thrift::ProtocolException.new(Thrift::ProtocolException::SIZE_LIMIT, "message")
-      prot.type.should == Thrift::ProtocolException::SIZE_LIMIT
-      prot.message.should == "message"
+      expect(prot.type).to eq(Thrift::ProtocolException::SIZE_LIMIT)
+      expect(prot.message).to eq("message")
     end
   end
 end
diff --git a/lib/rb/spec/flat_spec.rb b/lib/rb/spec/flat_spec.rb
index f378782..893056c 100644
--- a/lib/rb/spec/flat_spec.rb
+++ b/lib/rb/spec/flat_spec.rb
@@ -32,7 +32,7 @@
      "other_namespace/referenced_constants.rb",
      "other_namespace/referenced_types.rb"
     ].each do |name|
-      File.exist?(File.join(prefix, name)).should_not be_true
+      expect(File.exist?(File.join(prefix, name))).not_to be_truthy
     end
   end
 
@@ -44,19 +44,19 @@
      "referenced_constants.rb",
      "referenced_types.rb"
     ].each do |name|
-      File.exist?(File.join(prefix, name)).should be_true
+      expect(File.exist?(File.join(prefix, name))).to be_truthy
     end
   end
 
   it "has a service class in the right place" do
-    defined?(NamespacedSpecNamespace::NamespacedNonblockingService).should be_true
+    expect(defined?(NamespacedSpecNamespace::NamespacedNonblockingService)).to be_truthy
   end
 
   it "has a struct in the right place" do
-    defined?(NamespacedSpecNamespace::Hello).should be_true
+    expect(defined?(NamespacedSpecNamespace::Hello)).to be_truthy
   end
 
   it "required an included file" do
-    defined?(OtherNamespace::SomeEnum).should be_true
+    expect(defined?(OtherNamespace::SomeEnum)).to be_truthy
   end
 end
diff --git a/lib/rb/spec/http_client_spec.rb b/lib/rb/spec/http_client_spec.rb
index 5e8da24..df472ab 100644
--- a/lib/rb/spec/http_client_spec.rb
+++ b/lib/rb/spec/http_client_spec.rb
@@ -25,28 +25,32 @@
     before(:each) do
       @client = Thrift::HTTPClientTransport.new("http://my.domain.com/path/to/service?param=value")
     end
+    
+    it "should provide a reasonable to_s" do
+      @client.to_s == "http://my.domain.com/path/to/service?param=value"
+    end
 
     it "should always be open" do
-      @client.should be_open
+      expect(@client).to be_open
       @client.close
-      @client.should be_open
+      expect(@client).to be_open
     end
 
     it "should post via HTTP and return the results" do
       @client.write "a test"
       @client.write " frame"
-      Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
-        mock("Net::HTTP").tap do |http|
-          http.should_receive(:use_ssl=).with(false)
-          http.should_receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}).and_return do
-            mock("Net::HTTPOK").tap do |response|
-              response.should_receive(:body).and_return "data"
+      expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do
+        double("Net::HTTP").tap do |http|
+          expect(http).to receive(:use_ssl=).with(false)
+          expect(http).to receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}) do
+            double("Net::HTTPOK").tap do |response|
+              expect(response).to receive(:body).and_return "data"
             end
           end
         end
       end
       @client.flush
-      @client.read(10).should == "data"
+      expect(@client.read(10)).to eq("data")
     end
 
     it "should send custom headers if defined" do
@@ -55,12 +59,12 @@
       headers = {"Content-Type"=>"application/x-thrift"}.merge(custom_headers)
 
       @client.add_headers(custom_headers)
-      Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
-        mock("Net::HTTP").tap do |http|
-          http.should_receive(:use_ssl=).with(false)
-          http.should_receive(:post).with("/path/to/service?param=value", "test", headers).and_return do
-            mock("Net::HTTPOK").tap do |response|
-              response.should_receive(:body).and_return "data"
+      expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do
+        double("Net::HTTP").tap do |http|
+          expect(http).to receive(:use_ssl=).with(false)
+          expect(http).to receive(:post).with("/path/to/service?param=value", "test", headers) do
+            double("Net::HTTPOK").tap do |response|
+              expect(response).to receive(:body).and_return "data"
             end
           end
         end
@@ -71,15 +75,15 @@
     it 'should reset the outbuf on HTTP failures' do
       @client.write "test"
 
-      Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
-        mock("Net::HTTP").tap do |http|
-          http.should_receive(:use_ssl=).with(false)
-          http.should_receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) { raise Net::ReadTimeout }
+      expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do
+        double("Net::HTTP").tap do |http|
+          expect(http).to receive(:use_ssl=).with(false)
+          expect(http).to receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) { raise Net::ReadTimeout }
         end
       end
 
       @client.flush  rescue
-      @client.instance_variable_get(:@outbuf).should eq(Thrift::Bytes.empty_byte_buffer)
+      expect(@client.instance_variable_get(:@outbuf)).to eq(Thrift::Bytes.empty_byte_buffer)
     end
 
   end
@@ -95,20 +99,20 @@
 
       client.write "test"
 
-      Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
-        mock("Net::HTTP").tap do |http|
-          http.should_receive(:use_ssl=).with(true)
-          http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
-          http.should_receive(:post).with(@service_path, "test",
-              "Content-Type" => "application/x-thrift").and_return do
-            mock("Net::HTTPOK").tap do |response|
-              response.should_receive(:body).and_return "data"
+      expect(Net::HTTP).to receive(:new).with("my.domain.com", 443) do
+        double("Net::HTTP").tap do |http|
+          expect(http).to receive(:use_ssl=).with(true)
+          expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
+          expect(http).to receive(:post).with(@service_path, "test",
+              "Content-Type" => "application/x-thrift") do
+            double("Net::HTTPOK").tap do |response|
+              expect(response).to receive(:body).and_return "data"
             end
           end
         end
       end
       client.flush
-      client.read(4).should == "data"
+      expect(client.read(4)).to eq("data")
     end
 
     it "should set SSL verify mode when specified" do
@@ -116,20 +120,20 @@
           :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)
 
       client.write "test"
-      Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
-        mock("Net::HTTP").tap do |http|
-          http.should_receive(:use_ssl=).with(true)
-          http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
-          http.should_receive(:post).with(@service_path, "test",
-              "Content-Type" => "application/x-thrift").and_return do
-            mock("Net::HTTPOK").tap do |response|
-              response.should_receive(:body).and_return "data"
+      expect(Net::HTTP).to receive(:new).with("my.domain.com", 443) do
+        double("Net::HTTP").tap do |http|
+          expect(http).to receive(:use_ssl=).with(true)
+          expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+          expect(http).to receive(:post).with(@service_path, "test",
+              "Content-Type" => "application/x-thrift") do
+            double("Net::HTTPOK").tap do |response|
+              expect(response).to receive(:body).and_return "data"
             end
           end
         end
       end
       client.flush
-      client.read(4).should == "data"
+      expect(client.read(4)).to eq("data")
     end
   end
 end
diff --git a/lib/rb/spec/json_protocol_spec.rb b/lib/rb/spec/json_protocol_spec.rb
index b6b46bf..fe1af7b 100644
--- a/lib/rb/spec/json_protocol_spec.rb
+++ b/lib/rb/spec/json_protocol_spec.rb
@@ -30,257 +30,257 @@
 
     it "should write json escaped char" do
       @prot.write_json_escape_char("\n")
-      @trans.read(@trans.available).should == '\u000a'
+      expect(@trans.read(@trans.available)).to eq('\u000a')
 
       @prot.write_json_escape_char(" ")
-      @trans.read(@trans.available).should == '\u0020'
+      expect(@trans.read(@trans.available)).to eq('\u0020')
     end
 
     it "should write json char" do
       @prot.write_json_char("\n")
-      @trans.read(@trans.available).should == '\\n'
+      expect(@trans.read(@trans.available)).to eq('\\n')
 
       @prot.write_json_char(" ")
-      @trans.read(@trans.available).should == ' '
+      expect(@trans.read(@trans.available)).to eq(' ')
 
       @prot.write_json_char("\\")
-      @trans.read(@trans.available).should == "\\\\"
+      expect(@trans.read(@trans.available)).to eq("\\\\")
 
       @prot.write_json_char("@")
-      @trans.read(@trans.available).should == '@'
+      expect(@trans.read(@trans.available)).to eq('@')
     end
 
     it "should write json string" do
       @prot.write_json_string("this is a \\ json\nstring")
-      @trans.read(@trans.available).should == "\"this is a \\\\ json\\nstring\""
+      expect(@trans.read(@trans.available)).to eq("\"this is a \\\\ json\\nstring\"")
     end
 
     it "should write json base64" do
       @prot.write_json_base64("this is a base64 string")
-      @trans.read(@trans.available).should == "\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\""
+      expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"")
     end
 
     it "should write json integer" do
       @prot.write_json_integer(45)
-      @trans.read(@trans.available).should == "45"
+      expect(@trans.read(@trans.available)).to eq("45")
 
       @prot.write_json_integer(33000)
-      @trans.read(@trans.available).should == "33000"
+      expect(@trans.read(@trans.available)).to eq("33000")
 
       @prot.write_json_integer(3000000000)
-      @trans.read(@trans.available).should == "3000000000"
+      expect(@trans.read(@trans.available)).to eq("3000000000")
 
       @prot.write_json_integer(6000000000)
-      @trans.read(@trans.available).should == "6000000000"
+      expect(@trans.read(@trans.available)).to eq("6000000000")
     end
 
     it "should write json double" do
       @prot.write_json_double(12.3)
-      @trans.read(@trans.available).should == "12.3"
+      expect(@trans.read(@trans.available)).to eq("12.3")
 
       @prot.write_json_double(-3.21)
-      @trans.read(@trans.available).should == "-3.21"
+      expect(@trans.read(@trans.available)).to eq("-3.21")
 
       @prot.write_json_double(((+1.0/0.0)/(+1.0/0.0)))
-      @trans.read(@trans.available).should == "\"NaN\""
+      expect(@trans.read(@trans.available)).to eq("\"NaN\"")
 
       @prot.write_json_double((+1.0/0.0))
-      @trans.read(@trans.available).should == "\"Infinity\""
+      expect(@trans.read(@trans.available)).to eq("\"Infinity\"")
 
       @prot.write_json_double((-1.0/0.0))
-      @trans.read(@trans.available).should == "\"-Infinity\""
+      expect(@trans.read(@trans.available)).to eq("\"-Infinity\"")
     end
 
     it "should write json object start" do
       @prot.write_json_object_start
-      @trans.read(@trans.available).should == "{"
+      expect(@trans.read(@trans.available)).to eq("{")
     end
 
     it "should write json object end" do
       @prot.write_json_object_end
-      @trans.read(@trans.available).should == "}"
+      expect(@trans.read(@trans.available)).to eq("}")
     end
 
     it "should write json array start" do
       @prot.write_json_array_start
-      @trans.read(@trans.available).should == "["
+      expect(@trans.read(@trans.available)).to eq("[")
     end
 
     it "should write json array end" do
       @prot.write_json_array_end
-      @trans.read(@trans.available).should == "]"
+      expect(@trans.read(@trans.available)).to eq("]")
     end
 
     it "should write message begin" do
       @prot.write_message_begin("name", 12, 32)
-      @trans.read(@trans.available).should == "[1,\"name\",12,32"
+      expect(@trans.read(@trans.available)).to eq("[1,\"name\",12,32")
     end
 
     it "should write message end" do
       @prot.write_message_end
-      @trans.read(@trans.available).should == "]"
+      expect(@trans.read(@trans.available)).to eq("]")
     end
 
     it "should write struct begin" do
       @prot.write_struct_begin("name")
-      @trans.read(@trans.available).should == "{"
+      expect(@trans.read(@trans.available)).to eq("{")
     end
 
     it "should write struct end" do
       @prot.write_struct_end
-      @trans.read(@trans.available).should == "}"
+      expect(@trans.read(@trans.available)).to eq("}")
     end
 
     it "should write field begin" do
       @prot.write_field_begin("name", Thrift::Types::STRUCT, 32)
-      @trans.read(@trans.available).should == "32{\"rec\""
+      expect(@trans.read(@trans.available)).to eq("32{\"rec\"")
     end
 
     it "should write field end" do
       @prot.write_field_end
-      @trans.read(@trans.available).should == "}"
+      expect(@trans.read(@trans.available)).to eq("}")
     end
 
     it "should write field stop" do
       @prot.write_field_stop
-      @trans.read(@trans.available).should == ""
+      expect(@trans.read(@trans.available)).to eq("")
     end
 
     it "should write map begin" do
       @prot.write_map_begin(Thrift::Types::STRUCT, Thrift::Types::LIST, 32)
-      @trans.read(@trans.available).should == "[\"rec\",\"lst\",32,{"
+      expect(@trans.read(@trans.available)).to eq("[\"rec\",\"lst\",32,{")
     end
 
     it "should write map end" do
       @prot.write_map_end
-      @trans.read(@trans.available).should == "}]"
+      expect(@trans.read(@trans.available)).to eq("}]")
     end
 
     it "should write list begin" do
       @prot.write_list_begin(Thrift::Types::STRUCT, 32)
-      @trans.read(@trans.available).should == "[\"rec\",32"
+      expect(@trans.read(@trans.available)).to eq("[\"rec\",32")
     end
 
     it "should write list end" do
       @prot.write_list_end
-      @trans.read(@trans.available).should == "]"
+      expect(@trans.read(@trans.available)).to eq("]")
     end
 
     it "should write set begin" do
       @prot.write_set_begin(Thrift::Types::STRUCT, 32)
-      @trans.read(@trans.available).should == "[\"rec\",32"
+      expect(@trans.read(@trans.available)).to eq("[\"rec\",32")
     end
 
     it "should write set end" do
       @prot.write_set_end
-      @trans.read(@trans.available).should == "]"
+      expect(@trans.read(@trans.available)).to eq("]")
     end
 
     it "should write bool" do
       @prot.write_bool(true)
-      @trans.read(@trans.available).should == "1"
+      expect(@trans.read(@trans.available)).to eq("1")
 
       @prot.write_bool(false)
-      @trans.read(@trans.available).should == "0"
+      expect(@trans.read(@trans.available)).to eq("0")
     end
 
     it "should write byte" do
       @prot.write_byte(100)
-      @trans.read(@trans.available).should == "100"
+      expect(@trans.read(@trans.available)).to eq("100")
     end
 
     it "should write i16" do
       @prot.write_i16(1000)
-      @trans.read(@trans.available).should == "1000"
+      expect(@trans.read(@trans.available)).to eq("1000")
     end
 
     it "should write i32" do
       @prot.write_i32(3000000000)
-      @trans.read(@trans.available).should == "3000000000"
+      expect(@trans.read(@trans.available)).to eq("3000000000")
     end
 
     it "should write i64" do
       @prot.write_i64(6000000000)
-      @trans.read(@trans.available).should == "6000000000"
+      expect(@trans.read(@trans.available)).to eq("6000000000")
     end
 
     it "should write double" do
       @prot.write_double(1.23)
-      @trans.read(@trans.available).should == "1.23"
+      expect(@trans.read(@trans.available)).to eq("1.23")
 
       @prot.write_double(-32.1)
-      @trans.read(@trans.available).should == "-32.1"
+      expect(@trans.read(@trans.available)).to eq("-32.1")
 
       @prot.write_double(((+1.0/0.0)/(+1.0/0.0)))
-      @trans.read(@trans.available).should == "\"NaN\""
+      expect(@trans.read(@trans.available)).to eq("\"NaN\"")
 
       @prot.write_double((+1.0/0.0))
-      @trans.read(@trans.available).should == "\"Infinity\""
+      expect(@trans.read(@trans.available)).to eq("\"Infinity\"")
 
       @prot.write_double((-1.0/0.0))
-      @trans.read(@trans.available).should == "\"-Infinity\""
+      expect(@trans.read(@trans.available)).to eq("\"-Infinity\"")
     end
 
     if RUBY_VERSION >= '1.9'
       it 'should write string' do
         @prot.write_string('this is a test string')
         a = @trans.read(@trans.available)
-        a.should == '"this is a test string"'.force_encoding(Encoding::BINARY)
-        a.encoding.should == Encoding::BINARY
+        expect(a).to eq('"this is a test string"'.force_encoding(Encoding::BINARY))
+        expect(a.encoding).to eq(Encoding::BINARY)
       end
 
       it 'should write string with unicode characters' do
         @prot.write_string("this is a test string with unicode characters: \u20AC \u20AD")
         a = @trans.read(@trans.available)
-        a.should == "\"this is a test string with unicode characters: \u20AC \u20AD\"".force_encoding(Encoding::BINARY)
-        a.encoding.should == Encoding::BINARY
+        expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".force_encoding(Encoding::BINARY))
+        expect(a.encoding).to eq(Encoding::BINARY)
       end
     else
       it 'should write string' do
         @prot.write_string('this is a test string')
-        @trans.read(@trans.available).should == '"this is a test string"'
+        expect(@trans.read(@trans.available)).to eq('"this is a test string"')
       end
     end
 
     it "should write binary" do
       @prot.write_binary("this is a base64 string")
-      @trans.read(@trans.available).should == "\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\""
+      expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"")
     end
 
     it "should write long binary" do
       @prot.write_binary((0...256).to_a.pack('C*'))
-      @trans.read(@trans.available).should == "\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\""
+      expect(@trans.read(@trans.available)).to eq("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"")
     end
 
     it "should get type name for type id" do
       expect {@prot.get_type_name_for_type_id(Thrift::Types::STOP)}.to raise_error(NotImplementedError)
       expect {@prot.get_type_name_for_type_id(Thrift::Types::VOID)}.to raise_error(NotImplementedError)
-      @prot.get_type_name_for_type_id(Thrift::Types::BOOL).should == "tf"
-      @prot.get_type_name_for_type_id(Thrift::Types::BYTE).should == "i8"
-      @prot.get_type_name_for_type_id(Thrift::Types::DOUBLE).should == "dbl"
-      @prot.get_type_name_for_type_id(Thrift::Types::I16).should == "i16"
-      @prot.get_type_name_for_type_id(Thrift::Types::I32).should == "i32"
-      @prot.get_type_name_for_type_id(Thrift::Types::I64).should == "i64"
-      @prot.get_type_name_for_type_id(Thrift::Types::STRING).should == "str"
-      @prot.get_type_name_for_type_id(Thrift::Types::STRUCT).should == "rec"
-      @prot.get_type_name_for_type_id(Thrift::Types::MAP).should == "map"
-      @prot.get_type_name_for_type_id(Thrift::Types::SET).should == "set"
-      @prot.get_type_name_for_type_id(Thrift::Types::LIST).should == "lst"
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::BOOL)).to eq("tf")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::BYTE)).to eq("i8")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::DOUBLE)).to eq("dbl")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::I16)).to eq("i16")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::I32)).to eq("i32")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::I64)).to eq("i64")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::STRING)).to eq("str")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::STRUCT)).to eq("rec")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::MAP)).to eq("map")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::SET)).to eq("set")
+      expect(@prot.get_type_name_for_type_id(Thrift::Types::LIST)).to eq("lst")
     end
 
     it "should get type id for type name" do
       expect {@prot.get_type_id_for_type_name("pp")}.to raise_error(NotImplementedError)
-      @prot.get_type_id_for_type_name("tf").should == Thrift::Types::BOOL
-      @prot.get_type_id_for_type_name("i8").should == Thrift::Types::BYTE
-      @prot.get_type_id_for_type_name("dbl").should == Thrift::Types::DOUBLE
-      @prot.get_type_id_for_type_name("i16").should == Thrift::Types::I16
-      @prot.get_type_id_for_type_name("i32").should == Thrift::Types::I32
-      @prot.get_type_id_for_type_name("i64").should == Thrift::Types::I64
-      @prot.get_type_id_for_type_name("str").should == Thrift::Types::STRING
-      @prot.get_type_id_for_type_name("rec").should == Thrift::Types::STRUCT
-      @prot.get_type_id_for_type_name("map").should == Thrift::Types::MAP
-      @prot.get_type_id_for_type_name("set").should == Thrift::Types::SET
-      @prot.get_type_id_for_type_name("lst").should == Thrift::Types::LIST
+      expect(@prot.get_type_id_for_type_name("tf")).to eq(Thrift::Types::BOOL)
+      expect(@prot.get_type_id_for_type_name("i8")).to eq(Thrift::Types::BYTE)
+      expect(@prot.get_type_id_for_type_name("dbl")).to eq(Thrift::Types::DOUBLE)
+      expect(@prot.get_type_id_for_type_name("i16")).to eq(Thrift::Types::I16)
+      expect(@prot.get_type_id_for_type_name("i32")).to eq(Thrift::Types::I32)
+      expect(@prot.get_type_id_for_type_name("i64")).to eq(Thrift::Types::I64)
+      expect(@prot.get_type_id_for_type_name("str")).to eq(Thrift::Types::STRING)
+      expect(@prot.get_type_id_for_type_name("rec")).to eq(Thrift::Types::STRUCT)
+      expect(@prot.get_type_id_for_type_name("map")).to eq(Thrift::Types::MAP)
+      expect(@prot.get_type_id_for_type_name("set")).to eq(Thrift::Types::SET)
+      expect(@prot.get_type_id_for_type_name("lst")).to eq(Thrift::Types::LIST)
     end
 
     it "should read json syntax char" do
@@ -292,31 +292,31 @@
 
     it "should read json escape char" do
       @trans.write('0054')
-      @prot.read_json_escape_char.should == 'T'
+      expect(@prot.read_json_escape_char).to eq('T')
 
       @trans.write("\"\\\"\"")
-      @prot.read_json_string(false).should == "\""
+      expect(@prot.read_json_string(false)).to eq("\"")
 
       @trans.write("\"\\\\\"")
-      @prot.read_json_string(false).should == "\\"
+      expect(@prot.read_json_string(false)).to eq("\\")
 
       @trans.write("\"\\/\"")
-      @prot.read_json_string(false).should == "\/"
+      expect(@prot.read_json_string(false)).to eq("\/")
 
       @trans.write("\"\\b\"")
-      @prot.read_json_string(false).should == "\b"
+      expect(@prot.read_json_string(false)).to eq("\b")
 
       @trans.write("\"\\f\"")
-      @prot.read_json_string(false).should == "\f"
+      expect(@prot.read_json_string(false)).to eq("\f")
 
       @trans.write("\"\\n\"")
-      @prot.read_json_string(false).should == "\n"
+      expect(@prot.read_json_string(false)).to eq("\n")
 
       @trans.write("\"\\r\"")
-      @prot.read_json_string(false).should == "\r"
+      expect(@prot.read_json_string(false)).to eq("\r")
 
       @trans.write("\"\\t\"")
-      @prot.read_json_string(false).should == "\t"
+      expect(@prot.read_json_string(false)).to eq("\t")
     end
 
     it "should read json string" do
@@ -324,36 +324,36 @@
       expect {@prot.read_json_string(false)}.to raise_error(Thrift::ProtocolException)
 
       @trans.write("\"this is a test string\"")
-      @prot.read_json_string.should == "this is a test string"
+      expect(@prot.read_json_string).to eq("this is a test string")
     end
 
     it "should read json base64" do
       @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"")
-      @prot.read_json_base64.should == "this is a test string"
+      expect(@prot.read_json_base64).to eq("this is a test string")
     end
 
     it "should is json numeric" do
-      @prot.is_json_numeric("A").should == false
-      @prot.is_json_numeric("+").should == true
-      @prot.is_json_numeric("-").should == true
-      @prot.is_json_numeric(".").should == true
-      @prot.is_json_numeric("0").should == true
-      @prot.is_json_numeric("1").should == true
-      @prot.is_json_numeric("2").should == true
-      @prot.is_json_numeric("3").should == true
-      @prot.is_json_numeric("4").should == true
-      @prot.is_json_numeric("5").should == true
-      @prot.is_json_numeric("6").should == true
-      @prot.is_json_numeric("7").should == true
-      @prot.is_json_numeric("8").should == true
-      @prot.is_json_numeric("9").should == true
-      @prot.is_json_numeric("E").should == true
-      @prot.is_json_numeric("e").should == true
+      expect(@prot.is_json_numeric("A")).to eq(false)
+      expect(@prot.is_json_numeric("+")).to eq(true)
+      expect(@prot.is_json_numeric("-")).to eq(true)
+      expect(@prot.is_json_numeric(".")).to eq(true)
+      expect(@prot.is_json_numeric("0")).to eq(true)
+      expect(@prot.is_json_numeric("1")).to eq(true)
+      expect(@prot.is_json_numeric("2")).to eq(true)
+      expect(@prot.is_json_numeric("3")).to eq(true)
+      expect(@prot.is_json_numeric("4")).to eq(true)
+      expect(@prot.is_json_numeric("5")).to eq(true)
+      expect(@prot.is_json_numeric("6")).to eq(true)
+      expect(@prot.is_json_numeric("7")).to eq(true)
+      expect(@prot.is_json_numeric("8")).to eq(true)
+      expect(@prot.is_json_numeric("9")).to eq(true)
+      expect(@prot.is_json_numeric("E")).to eq(true)
+      expect(@prot.is_json_numeric("e")).to eq(true)
     end
 
     it "should read json numeric chars" do
       @trans.write("1.453E45T")
-      @prot.read_json_numeric_chars.should == "1.453E45"
+      expect(@prot.read_json_numeric_chars).to eq("1.453E45")
     end
 
     it "should read json integer" do
@@ -362,7 +362,7 @@
       @prot.read_string
 
       @trans.write("1453T")
-      @prot.read_json_integer.should == 1453
+      expect(@prot.read_json_integer).to eq(1453)
     end
 
     it "should read json double" do
@@ -374,37 +374,37 @@
       expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException)
 
       @trans.write("1.453e01\"\"")
-      @prot.read_json_double.should == 14.53
+      expect(@prot.read_json_double).to eq(14.53)
       @prot.read_string
 
       @trans.write("\"NaN\"")
-      @prot.read_json_double.nan?.should == true
+      expect(@prot.read_json_double.nan?).to eq(true)
 
       @trans.write("\"Infinity\"")
-      @prot.read_json_double.should == +1.0/0.0
+      expect(@prot.read_json_double).to eq(+1.0/0.0)
 
       @trans.write("\"-Infinity\"")
-      @prot.read_json_double.should == -1.0/0.0
+      expect(@prot.read_json_double).to eq(-1.0/0.0)
     end
 
     it "should read json object start" do
       @trans.write("{")
-      @prot.read_json_object_start.should == nil
+      expect(@prot.read_json_object_start).to eq(nil)
     end
 
     it "should read json object end" do
       @trans.write("}")
-      @prot.read_json_object_end.should == nil
+      expect(@prot.read_json_object_end).to eq(nil)
     end
 
     it "should read json array start" do
       @trans.write("[")
-      @prot.read_json_array_start.should == nil
+      expect(@prot.read_json_array_start).to eq(nil)
     end
 
     it "should read json array end" do
       @trans.write("]")
-      @prot.read_json_array_end.should == nil
+      expect(@prot.read_json_array_end).to eq(nil)
     end
 
     it "should read_message_begin" do
@@ -412,133 +412,141 @@
       expect {@prot.read_message_begin}.to raise_error(Thrift::ProtocolException)
 
       @trans.write("[1,\"name\",12,32\"\"")
-      @prot.read_message_begin.should == ["name", 12, 32]
+      expect(@prot.read_message_begin).to eq(["name", 12, 32])
     end
 
     it "should read message end" do
       @trans.write("]")
-      @prot.read_message_end.should == nil
+      expect(@prot.read_message_end).to eq(nil)
     end
 
     it "should read struct begin" do
       @trans.write("{")
-      @prot.read_struct_begin.should == nil
+      expect(@prot.read_struct_begin).to eq(nil)
     end
 
     it "should read struct end" do
       @trans.write("}")
-      @prot.read_struct_end.should == nil
+      expect(@prot.read_struct_end).to eq(nil)
     end
 
     it "should read field begin" do
       @trans.write("1{\"rec\"")
-      @prot.read_field_begin.should == [nil, 12, 1]
+      expect(@prot.read_field_begin).to eq([nil, 12, 1])
     end
 
     it "should read field end" do
       @trans.write("}")
-      @prot.read_field_end.should == nil
+      expect(@prot.read_field_end).to eq(nil)
     end
 
     it "should read map begin" do
       @trans.write("[\"rec\",\"lst\",2,{")
-      @prot.read_map_begin.should == [12, 15, 2]
+      expect(@prot.read_map_begin).to eq([12, 15, 2])
     end
 
     it "should read map end" do
       @trans.write("}]")
-      @prot.read_map_end.should == nil
+      expect(@prot.read_map_end).to eq(nil)
     end
 
     it "should read list begin" do
       @trans.write("[\"rec\",2\"\"")
-      @prot.read_list_begin.should == [12, 2]
+      expect(@prot.read_list_begin).to eq([12, 2])
     end
 
     it "should read list end" do
       @trans.write("]")
-      @prot.read_list_end.should == nil
+      expect(@prot.read_list_end).to eq(nil)
     end
 
     it "should read set begin" do
       @trans.write("[\"rec\",2\"\"")
-      @prot.read_set_begin.should == [12, 2]
+      expect(@prot.read_set_begin).to eq([12, 2])
     end
 
     it "should read set end" do
       @trans.write("]")
-      @prot.read_set_end.should == nil
+      expect(@prot.read_set_end).to eq(nil)
     end
 
     it "should read bool" do
       @trans.write("0\"\"")
-      @prot.read_bool.should == false
+      expect(@prot.read_bool).to eq(false)
       @prot.read_string
 
       @trans.write("1\"\"")
-      @prot.read_bool.should == true
+      expect(@prot.read_bool).to eq(true)
     end
 
     it "should read byte" do
       @trans.write("60\"\"")
-      @prot.read_byte.should == 60
+      expect(@prot.read_byte).to eq(60)
     end
 
     it "should read i16" do
       @trans.write("1000\"\"")
-      @prot.read_i16.should == 1000
+      expect(@prot.read_i16).to eq(1000)
     end
 
     it "should read i32" do
       @trans.write("3000000000\"\"")
-      @prot.read_i32.should == 3000000000
+      expect(@prot.read_i32).to eq(3000000000)
     end
 
     it "should read i64" do
       @trans.write("6000000000\"\"")
-      @prot.read_i64.should == 6000000000
+      expect(@prot.read_i64).to eq(6000000000)
     end
 
     it "should read double" do
       @trans.write("12.23\"\"")
-      @prot.read_double.should == 12.23
+      expect(@prot.read_double).to eq(12.23)
     end
 
     if RUBY_VERSION >= '1.9'
       it 'should read string' do
         @trans.write('"this is a test string"'.force_encoding(Encoding::BINARY))
         a = @prot.read_string
-        a.should == 'this is a test string'
-        a.encoding.should == Encoding::UTF_8
+        expect(a).to eq('this is a test string')
+        expect(a.encoding).to eq(Encoding::UTF_8)
       end
 
       it 'should read string with unicode characters' do
         @trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.force_encoding(Encoding::BINARY))
         a = @prot.read_string
-        a.should == "this is a test string with unicode characters: \u20AC \u20AD"
-        a.encoding.should == Encoding::UTF_8
+        expect(a).to eq("this is a test string with unicode characters: \u20AC \u20AD")
+        expect(a.encoding).to eq(Encoding::UTF_8)
       end
     else
       it 'should read string' do
         @trans.write('"this is a test string"')
-        @prot.read_string.should == 'this is a test string'
+        expect(@prot.read_string).to eq('this is a test string')
       end
     end
 
     it "should read binary" do
       @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"")
-      @prot.read_binary.should == "this is a test string"
+      expect(@prot.read_binary).to eq("this is a test string")
     end
 
     it "should read long binary" do
       @trans.write("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"")
-      @prot.read_binary.bytes.to_a.should == (0...256).to_a
+      expect(@prot.read_binary.bytes.to_a).to eq((0...256).to_a)
+    end
+  
+    it "should provide a reasonable to_s" do
+      expect(@prot.to_s).to eq("json(memory)")
     end
   end
 
   describe Thrift::JsonProtocolFactory do
     it "should create a JsonProtocol" do
-      Thrift::JsonProtocolFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(Thrift::JsonProtocol)
+      expect(Thrift::JsonProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::JsonProtocol)
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(Thrift::JsonProtocolFactory.new.to_s).to eq("json")
     end
   end
 end
diff --git a/lib/rb/spec/namespaced_spec.rb b/lib/rb/spec/namespaced_spec.rb
index 31379d9..4d6d369 100644
--- a/lib/rb/spec/namespaced_spec.rb
+++ b/lib/rb/spec/namespaced_spec.rb
@@ -32,7 +32,7 @@
      "other_namespace/referenced_constants.rb",
      "other_namespace/referenced_types.rb"
     ].each do |name|
-      File.exist?(File.join(prefix, name)).should be_true
+      expect(File.exist?(File.join(prefix, name))).to be_truthy
     end
   end
 
@@ -44,20 +44,20 @@
      "referenced_constants.rb",
      "referenced_types.rb"
     ].each do |name|
-      File.exist?(File.join(prefix, name)).should_not be_true
+      expect(File.exist?(File.join(prefix, name))).not_to be_truthy
     end
   end
 
   it "has a service class in the right place" do
-    defined?(NamespacedSpecNamespace::NamespacedNonblockingService).should be_true
+    expect(defined?(NamespacedSpecNamespace::NamespacedNonblockingService)).to be_truthy
   end
 
   it "has a struct in the right place" do
-    defined?(NamespacedSpecNamespace::Hello).should be_true
+    expect(defined?(NamespacedSpecNamespace::Hello)).to be_truthy
   end
 
   it "required an included file" do
-    defined?(OtherNamespace::SomeEnum).should be_true
+    expect(defined?(OtherNamespace::SomeEnum)).to be_truthy
   end
 
   it "extended a service" do
diff --git a/lib/rb/spec/nonblocking_server_spec.rb b/lib/rb/spec/nonblocking_server_spec.rb
index 712cf45..613d883 100644
--- a/lib/rb/spec/nonblocking_server_spec.rb
+++ b/lib/rb/spec/nonblocking_server_spec.rb
@@ -176,8 +176,8 @@
 
     it "should handle basic message passing" do
       client = setup_client
-      client.greeting(true).should == SpecNamespace::Hello.new
-      client.greeting(false).should == SpecNamespace::Hello.new(:greeting => 'Aloha!')
+      expect(client.greeting(true)).to eq(SpecNamespace::Hello.new)
+      expect(client.greeting(false)).to eq(SpecNamespace::Hello.new(:greeting => 'Aloha!'))
       @server.shutdown
     end
 
@@ -195,7 +195,7 @@
       end
       4.times { trans_queue.pop }
       setup_client.unblock(4)
-      4.times { queue.pop.should be_true }
+      4.times { expect(queue.pop).to be_truthy }
       @server.shutdown
     end
 
@@ -212,15 +212,15 @@
       queues[4] << :hello
       queues[5] << :hello
       queues[6] << :hello
-      3.times { result.pop.should == SpecNamespace::Hello.new }
-      client.greeting(true).should == SpecNamespace::Hello.new
+      3.times { expect(result.pop).to eq(SpecNamespace::Hello.new) }
+      expect(client.greeting(true)).to eq(SpecNamespace::Hello.new)
       queues[5] << [:unblock, 4]
-      4.times { result.pop.should be_true }
+      4.times { expect(result.pop).to be_truthy }
       queues[2] << :hello
-      result.pop.should == SpecNamespace::Hello.new
-      client.greeting(false).should == SpecNamespace::Hello.new(:greeting => 'Aloha!')
+      expect(result.pop).to eq(SpecNamespace::Hello.new)
+      expect(client.greeting(false)).to eq(SpecNamespace::Hello.new(:greeting => 'Aloha!'))
       7.times { queues.shift << :exit }
-      client.greeting(true).should == SpecNamespace::Hello.new
+      expect(client.greeting(true)).to eq(SpecNamespace::Hello.new)
       @server.shutdown
     end
 
@@ -229,7 +229,7 @@
       client = setup_client
       client.greeting(false) # force a message pass
       @server.shutdown
-      @server_thread.join(2).should be_an_instance_of(Thread)
+      expect(@server_thread.join(2)).to be_an_instance_of(Thread)
     end
 
     it "should continue processing active messages when shutting down" do
@@ -238,8 +238,8 @@
       client << :sleep
       sleep 0.1 # give the server time to start processing the client's message
       @server.shutdown
-      @server_thread.join(2).should be_an_instance_of(Thread)
-      result.pop.should == :slept
+      expect(@server_thread.join(2)).to be_an_instance_of(Thread)
+      expect(result.pop).to eq(:slept)
     end
 
     it "should kill active messages when they don't expire while shutting down" do
@@ -249,15 +249,15 @@
       sleep 0.1 # start processing the client's message
       @server.shutdown(1)
       @catch_exceptions = true
-      @server_thread.join(3).should_not be_nil
-      result.should be_empty
+      expect(@server_thread.join(3)).not_to be_nil
+      expect(result).to be_empty
     end
 
     it "should allow shutting down in response to a message" do
       client = setup_client
-      client.greeting(true).should == SpecNamespace::Hello.new
+      expect(client.greeting(true)).to eq(SpecNamespace::Hello.new)
       client.shutdown
-      @server_thread.join(2).should_not be_nil
+      expect(@server_thread.join(2)).not_to be_nil
     end
   end
 end
diff --git a/lib/rb/spec/processor_spec.rb b/lib/rb/spec/processor_spec.rb
index 989f5cc..d30553f 100644
--- a/lib/rb/spec/processor_spec.rb
+++ b/lib/rb/spec/processor_spec.rb
@@ -27,52 +27,52 @@
 
   describe Thrift::Processor do
     before(:each) do
-      @processor = ProcessorSpec.new(mock("MockHandler"))
-      @prot = mock("MockProtocol")
+      @processor = ProcessorSpec.new(double("MockHandler"))
+      @prot = double("MockProtocol")
     end
 
     def mock_trans(obj)
-      obj.should_receive(:trans).ordered.and_return do
-        mock("trans").tap do |trans|
-          trans.should_receive(:flush).ordered
+      expect(obj).to receive(:trans).ordered do
+        double("trans").tap do |trans|
+          expect(trans).to receive(:flush).ordered
         end
       end
     end
 
     it "should call process_<message> when it receives that message" do
-      @prot.should_receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 17]
-      @processor.should_receive(:process_testMessage).with(17, @prot, @prot).ordered
-      @processor.process(@prot, @prot).should == true
+      expect(@prot).to receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 17]
+      expect(@processor).to receive(:process_testMessage).with(17, @prot, @prot).ordered
+      expect(@processor.process(@prot, @prot)).to eq(true)
     end
 
     it "should raise an ApplicationException when the received message cannot be processed" do
-      @prot.should_receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 4]
-      @prot.should_receive(:skip).with(Thrift::Types::STRUCT).ordered
-      @prot.should_receive(:read_message_end).ordered
-      @prot.should_receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::EXCEPTION, 4).ordered
-      e = mock(Thrift::ApplicationException)
-      e.should_receive(:write).with(@prot).ordered
-      Thrift::ApplicationException.should_receive(:new).with(Thrift::ApplicationException::UNKNOWN_METHOD, "Unknown function testMessage").and_return(e)
-      @prot.should_receive(:write_message_end).ordered
+      expect(@prot).to receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 4]
+      expect(@prot).to receive(:skip).with(Thrift::Types::STRUCT).ordered
+      expect(@prot).to receive(:read_message_end).ordered
+      expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::EXCEPTION, 4).ordered
+      e = double(Thrift::ApplicationException)
+      expect(e).to receive(:write).with(@prot).ordered
+      expect(Thrift::ApplicationException).to receive(:new).with(Thrift::ApplicationException::UNKNOWN_METHOD, "Unknown function testMessage").and_return(e)
+      expect(@prot).to receive(:write_message_end).ordered
       mock_trans(@prot)
       @processor.process(@prot, @prot)
     end
 
     it "should pass args off to the args class" do
-      args_class = mock("MockArgsClass")
-      args = mock("#<MockArgsClass:mock>").tap do |args|
-        args.should_receive(:read).with(@prot).ordered
+      args_class = double("MockArgsClass")
+      args = double("#<MockArgsClass:mock>").tap do |args|
+        expect(args).to receive(:read).with(@prot).ordered
       end
-      args_class.should_receive(:new).and_return args
-      @prot.should_receive(:read_message_end).ordered
-      @processor.read_args(@prot, args_class).should eql(args)
+      expect(args_class).to receive(:new).and_return args
+      expect(@prot).to receive(:read_message_end).ordered
+      expect(@processor.read_args(@prot, args_class)).to eql(args)
     end
 
     it "should write out a reply when asked" do
-      @prot.should_receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::REPLY, 23).ordered
-      result = mock("MockResult")
-      result.should_receive(:write).with(@prot).ordered
-      @prot.should_receive(:write_message_end).ordered
+      expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::REPLY, 23).ordered
+      result = double("MockResult")
+      expect(result).to receive(:write).with(@prot).ordered
+      expect(@prot).to receive(:write_message_end).ordered
       mock_trans(@prot)
       @processor.write_result(result, @prot, 'testMessage', 23)
     end
diff --git a/lib/rb/spec/serializer_spec.rb b/lib/rb/spec/serializer_spec.rb
index 599b454..2a7dc6d 100644
--- a/lib/rb/spec/serializer_spec.rb
+++ b/lib/rb/spec/serializer_spec.rb
@@ -25,19 +25,19 @@
     it "should serialize structs to binary by default" do
       serializer = Thrift::Serializer.new(Thrift::BinaryProtocolAcceleratedFactory.new)
       data = serializer.serialize(SpecNamespace::Hello.new(:greeting => "'Ello guv'nor!"))
-      data.should == "\x0B\x00\x01\x00\x00\x00\x0E'Ello guv'nor!\x00"
+      expect(data).to eq("\x0B\x00\x01\x00\x00\x00\x0E'Ello guv'nor!\x00")
     end
 
     it "should serialize structs to the given protocol" do
-      protocol = Thrift::BaseProtocol.new(mock("transport"))
-      protocol.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
-      protocol.should_receive(:write_field_begin).with("greeting", Thrift::Types::STRING, 1)
-      protocol.should_receive(:write_string).with("Good day")
-      protocol.should_receive(:write_field_end)
-      protocol.should_receive(:write_field_stop)
-      protocol.should_receive(:write_struct_end)
-      protocol_factory = mock("ProtocolFactory")
-      protocol_factory.stub!(:get_protocol).and_return(protocol)
+      protocol = Thrift::BaseProtocol.new(double("transport"))
+      expect(protocol).to receive(:write_struct_begin).with("SpecNamespace::Hello")
+      expect(protocol).to receive(:write_field_begin).with("greeting", Thrift::Types::STRING, 1)
+      expect(protocol).to receive(:write_string).with("Good day")
+      expect(protocol).to receive(:write_field_end)
+      expect(protocol).to receive(:write_field_stop)
+      expect(protocol).to receive(:write_struct_end)
+      protocol_factory = double("ProtocolFactory")
+      allow(protocol_factory).to receive(:get_protocol).and_return(protocol)
       serializer = Thrift::Serializer.new(protocol_factory)
       serializer.serialize(SpecNamespace::Hello.new(:greeting => "Good day"))
     end
@@ -47,21 +47,21 @@
     it "should deserialize structs from binary by default" do
       deserializer = Thrift::Deserializer.new
       data = "\x0B\x00\x01\x00\x00\x00\x0E'Ello guv'nor!\x00"
-      deserializer.deserialize(SpecNamespace::Hello.new, data).should == SpecNamespace::Hello.new(:greeting => "'Ello guv'nor!")
+      expect(deserializer.deserialize(SpecNamespace::Hello.new, data)).to eq(SpecNamespace::Hello.new(:greeting => "'Ello guv'nor!"))
     end
 
     it "should deserialize structs from the given protocol" do
-      protocol = Thrift::BaseProtocol.new(mock("transport"))
-      protocol.should_receive(:read_struct_begin).and_return("SpecNamespace::Hello")
-      protocol.should_receive(:read_field_begin).and_return(["greeting", Thrift::Types::STRING, 1],
+      protocol = Thrift::BaseProtocol.new(double("transport"))
+      expect(protocol).to receive(:read_struct_begin).and_return("SpecNamespace::Hello")
+      expect(protocol).to receive(:read_field_begin).and_return(["greeting", Thrift::Types::STRING, 1],
                                                             [nil, Thrift::Types::STOP, 0])
-      protocol.should_receive(:read_string).and_return("Good day")
-      protocol.should_receive(:read_field_end)
-      protocol.should_receive(:read_struct_end)
-      protocol_factory = mock("ProtocolFactory")
-      protocol_factory.stub!(:get_protocol).and_return(protocol)
+      expect(protocol).to receive(:read_string).and_return("Good day")
+      expect(protocol).to receive(:read_field_end)
+      expect(protocol).to receive(:read_struct_end)
+      protocol_factory = double("ProtocolFactory")
+      allow(protocol_factory).to receive(:get_protocol).and_return(protocol)
       deserializer = Thrift::Deserializer.new(protocol_factory)
-      deserializer.deserialize(SpecNamespace::Hello.new, "").should == SpecNamespace::Hello.new(:greeting => "Good day")
+      expect(deserializer.deserialize(SpecNamespace::Hello.new, "")).to eq(SpecNamespace::Hello.new(:greeting => "Good day"))
     end
   end
 end
diff --git a/lib/rb/spec/server_socket_spec.rb b/lib/rb/spec/server_socket_spec.rb
index 1301d54..ec9e550 100644
--- a/lib/rb/spec/server_socket_spec.rb
+++ b/lib/rb/spec/server_socket_spec.rb
@@ -28,52 +28,57 @@
     end
 
     it "should create a handle when calling listen" do
-      TCPServer.should_receive(:new).with(nil, 1234)
+      expect(TCPServer).to receive(:new).with(nil, 1234)
       @socket.listen
     end
 
     it "should accept an optional host argument" do
       @socket = Thrift::ServerSocket.new('localhost', 1234)
-      TCPServer.should_receive(:new).with('localhost', 1234)
+      expect(TCPServer).to receive(:new).with('localhost', 1234)
+      @socket.to_s == "server(localhost:1234)"
       @socket.listen
     end
 
     it "should create a Thrift::Socket to wrap accepted sockets" do
-      handle = mock("TCPServer")
-      TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
+      handle = double("TCPServer")
+      expect(TCPServer).to receive(:new).with(nil, 1234).and_return(handle)
       @socket.listen
-      sock = mock("sock")
-      handle.should_receive(:accept).and_return(sock)
-      trans = mock("Socket")
-      Thrift::Socket.should_receive(:new).and_return(trans)
-      trans.should_receive(:handle=).with(sock)
-      @socket.accept.should == trans
+      sock = double("sock")
+      expect(handle).to receive(:accept).and_return(sock)
+      trans = double("Socket")
+      expect(Thrift::Socket).to receive(:new).and_return(trans)
+      expect(trans).to receive(:handle=).with(sock)
+      expect(@socket.accept).to eq(trans)
     end
 
     it "should close the handle when closed" do
-      handle = mock("TCPServer", :closed? => false)
-      TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
+      handle = double("TCPServer", :closed? => false)
+      expect(TCPServer).to receive(:new).with(nil, 1234).and_return(handle)
       @socket.listen
-      handle.should_receive(:close)
+      expect(handle).to receive(:close)
       @socket.close
     end
 
     it "should return nil when accepting if there is no handle" do
-      @socket.accept.should be_nil
+      expect(@socket.accept).to be_nil
     end
 
     it "should return true for closed? when appropriate" do
-      handle = mock("TCPServer", :closed? => false)
-      TCPServer.stub!(:new).and_return(handle)
+      handle = double("TCPServer", :closed? => false)
+      allow(TCPServer).to receive(:new).and_return(handle)
       @socket.listen
-      @socket.should_not be_closed
-      handle.stub!(:close)
+      expect(@socket).not_to be_closed
+      allow(handle).to receive(:close)
       @socket.close
-      @socket.should be_closed
+      expect(@socket).to be_closed
       @socket.listen
-      @socket.should_not be_closed
-      handle.stub!(:closed?).and_return(true)
-      @socket.should be_closed
+      expect(@socket).not_to be_closed
+      allow(handle).to receive(:closed?).and_return(true)
+      expect(@socket).to be_closed
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(@socket.to_s).to eq("socket(:1234)")
     end
   end
 end
diff --git a/lib/rb/spec/server_spec.rb b/lib/rb/spec/server_spec.rb
index 93b9195..57f5237 100644
--- a/lib/rb/spec/server_spec.rb
+++ b/lib/rb/spec/server_spec.rb
@@ -21,96 +21,135 @@
 describe 'Server' do
 
   describe Thrift::BaseServer do
-    it "should default to BaseTransportFactory and BinaryProtocolFactory when not specified" do
-      server = Thrift::BaseServer.new(mock("Processor"), mock("BaseServerTransport"))
-      server.instance_variable_get(:'@transport_factory').should be_an_instance_of(Thrift::BaseTransportFactory)
-      server.instance_variable_get(:'@protocol_factory').should be_an_instance_of(Thrift::BinaryProtocolFactory)
+    before(:each) do
+      @processor = double("Processor")
+      @serverTrans = double("ServerTransport")
+      @trans = double("BaseTransport")
+      @prot = double("BaseProtocol")
+      @server = described_class.new(@processor, @serverTrans, @trans, @prot)
     end
 
-    # serve is a noop, so can't test that
+    it "should default to BaseTransportFactory and BinaryProtocolFactory when not specified" do
+      @server = Thrift::BaseServer.new(double("Processor"), double("BaseServerTransport"))
+      expect(@server.instance_variable_get(:'@transport_factory')).to be_an_instance_of(Thrift::BaseTransportFactory)
+      expect(@server.instance_variable_get(:'@protocol_factory')).to be_an_instance_of(Thrift::BinaryProtocolFactory)
+    end
+
+    it "should not serve" do
+      expect { @server.serve()}.to raise_error(NotImplementedError)
+    end
+    
+    it "should provide a reasonable to_s" do
+      expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans")
+      expect(@trans).to receive(:to_s).once.and_return("trans")
+      expect(@prot).to receive(:to_s).once.and_return("prot")
+      expect(@server.to_s).to eq("server(prot(trans(serverTrans)))")
+    end
   end
 
   describe Thrift::SimpleServer do
     before(:each) do
-      @processor = mock("Processor")
-      @serverTrans = mock("ServerTransport")
-      @trans = mock("BaseTransport")
-      @prot = mock("BaseProtocol")
-      @client = mock("Client")
+      @processor = double("Processor")
+      @serverTrans = double("ServerTransport")
+      @trans = double("BaseTransport")
+      @prot = double("BaseProtocol")
+      @client = double("Client")
       @server = described_class.new(@processor, @serverTrans, @trans, @prot)
     end
     
+    it "should provide a reasonable to_s" do
+      expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans")
+      expect(@trans).to receive(:to_s).once.and_return("trans")
+      expect(@prot).to receive(:to_s).once.and_return("prot")
+      expect(@server.to_s).to eq("simple(server(prot(trans(serverTrans))))")
+    end
+    
     it "should serve in the main thread" do
-      @serverTrans.should_receive(:listen).ordered
-      @serverTrans.should_receive(:accept).exactly(3).times.and_return(@client)
-      @trans.should_receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
-      @prot.should_receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
+      expect(@serverTrans).to receive(:listen).ordered
+      expect(@serverTrans).to receive(:accept).exactly(3).times.and_return(@client)
+      expect(@trans).to receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
+      expect(@prot).to receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
       x = 0
-      @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
+      expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do
         case (x += 1)
         when 1 then raise Thrift::TransportException
         when 2 then raise Thrift::ProtocolException
         when 3 then throw :stop
         end
       end
-      @trans.should_receive(:close).exactly(3).times
-      @serverTrans.should_receive(:close).ordered
-      lambda { @server.serve }.should throw_symbol(:stop)
+      expect(@trans).to receive(:close).exactly(3).times
+      expect(@serverTrans).to receive(:close).ordered
+      expect { @server.serve }.to throw_symbol(:stop)
     end
   end
 
   describe Thrift::ThreadedServer do
     before(:each) do
-      @processor = mock("Processor")
-      @serverTrans = mock("ServerTransport")
-      @trans = mock("BaseTransport")
-      @prot = mock("BaseProtocol")
-      @client = mock("Client")
+      @processor = double("Processor")
+      @serverTrans = double("ServerTransport")
+      @trans = double("BaseTransport")
+      @prot = double("BaseProtocol")
+      @client = double("Client")
       @server = described_class.new(@processor, @serverTrans, @trans, @prot)
     end
 
+    it "should provide a reasonable to_s" do
+      expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans")
+      expect(@trans).to receive(:to_s).once.and_return("trans")
+      expect(@prot).to receive(:to_s).once.and_return("prot")
+      expect(@server.to_s).to eq("threaded(server(prot(trans(serverTrans))))")
+    end
+    
     it "should serve using threads" do
-      @serverTrans.should_receive(:listen).ordered
-      @serverTrans.should_receive(:accept).exactly(3).times.and_return(@client)
-      @trans.should_receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
-      @prot.should_receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
-      Thread.should_receive(:new).with(@prot, @trans).exactly(3).times.and_yield(@prot, @trans)
+      expect(@serverTrans).to receive(:listen).ordered
+      expect(@serverTrans).to receive(:accept).exactly(3).times.and_return(@client)
+      expect(@trans).to receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
+      expect(@prot).to receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
+      expect(Thread).to receive(:new).with(@prot, @trans).exactly(3).times.and_yield(@prot, @trans)
       x = 0
-      @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
+      expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do
         case (x += 1)
         when 1 then raise Thrift::TransportException
         when 2 then raise Thrift::ProtocolException
         when 3 then throw :stop
         end
       end
-      @trans.should_receive(:close).exactly(3).times
-      @serverTrans.should_receive(:close).ordered
-      lambda { @server.serve }.should throw_symbol(:stop)
+      expect(@trans).to receive(:close).exactly(3).times
+      expect(@serverTrans).to receive(:close).ordered
+      expect { @server.serve }.to throw_symbol(:stop)
     end
   end
 
   describe Thrift::ThreadPoolServer do
     before(:each) do
-      @processor = mock("Processor")
-      @server_trans = mock("ServerTransport")
-      @trans = mock("BaseTransport")
-      @prot = mock("BaseProtocol")
-      @client = mock("Client")
+      @processor = double("Processor")
+      @server_trans = double("ServerTransport")
+      @trans = double("BaseTransport")
+      @prot = double("BaseProtocol")
+      @client = double("Client")
       @server = described_class.new(@processor, @server_trans, @trans, @prot)
-      sleep(0.1)
+      sleep(0.15)
     end
 
+    it "should provide a reasonable to_s" do
+      expect(@server_trans).to receive(:to_s).once.and_return("server_trans")
+      expect(@trans).to receive(:to_s).once.and_return("trans")
+      expect(@prot).to receive(:to_s).once.and_return("prot")
+      expect(@server.to_s).to eq("threadpool(server(prot(trans(server_trans))))")
+    end
+    
     it "should serve inside a thread" do
       exception_q = @server.instance_variable_get(:@exception_q)
-      described_class.any_instance.should_receive(:serve) do 
+      expect_any_instance_of(described_class).to receive(:serve) do 
         exception_q.push(StandardError.new('ERROR'))
       end
       expect { @server.rescuable_serve }.to(raise_error('ERROR'))
+      sleep(0.15)
     end
 
     it "should avoid running the server twice when retrying rescuable_serve" do
       exception_q = @server.instance_variable_get(:@exception_q)
-      described_class.any_instance.should_receive(:serve) do 
+      expect_any_instance_of(described_class).to receive(:serve) do 
         exception_q.push(StandardError.new('ERROR1'))
         exception_q.push(StandardError.new('ERROR2'))
       end
@@ -119,29 +158,29 @@
     end
 
     it "should serve using a thread pool" do
-      thread_q = mock("SizedQueue")
-      exception_q = mock("Queue")
+      thread_q = double("SizedQueue")
+      exception_q = double("Queue")
       @server.instance_variable_set(:@thread_q, thread_q)
       @server.instance_variable_set(:@exception_q, exception_q)
-      @server_trans.should_receive(:listen).ordered
-      thread_q.should_receive(:push).with(:token)
-      thread_q.should_receive(:pop)
-      Thread.should_receive(:new).and_yield
-      @server_trans.should_receive(:accept).exactly(3).times.and_return(@client)
-      @trans.should_receive(:get_transport).exactly(3).times.and_return(@trans)
-      @prot.should_receive(:get_protocol).exactly(3).times.and_return(@prot)
+      expect(@server_trans).to receive(:listen).ordered
+      expect(thread_q).to receive(:push).with(:token)
+      expect(thread_q).to receive(:pop)
+      expect(Thread).to receive(:new).and_yield
+      expect(@server_trans).to receive(:accept).exactly(3).times.and_return(@client)
+      expect(@trans).to receive(:get_transport).exactly(3).times.and_return(@trans)
+      expect(@prot).to receive(:get_protocol).exactly(3).times.and_return(@prot)
       x = 0
       error = RuntimeError.new("Stopped")
-      @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
+      expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do
         case (x += 1)
         when 1 then raise Thrift::TransportException
         when 2 then raise Thrift::ProtocolException
         when 3 then raise error
         end
       end
-      @trans.should_receive(:close).exactly(3).times
-      exception_q.should_receive(:push).with(error).and_throw(:stop)
-      @server_trans.should_receive(:close)
+      expect(@trans).to receive(:close).exactly(3).times
+      expect(exception_q).to receive(:push).with(error).and_throw(:stop)
+      expect(@server_trans).to receive(:close)
       expect { @server.serve }.to(throw_symbol(:stop))
     end
   end
diff --git a/lib/rb/spec/socket_spec.rb b/lib/rb/spec/socket_spec.rb
index 8e1ef50..202c745 100644
--- a/lib/rb/spec/socket_spec.rb
+++ b/lib/rb/spec/socket_spec.rb
@@ -25,37 +25,44 @@
   describe Thrift::Socket do
     before(:each) do
       @socket = Thrift::Socket.new
-      @handle = mock("Handle", :closed? => false)
-      @handle.stub!(:close)
-      @handle.stub!(:connect_nonblock)
-      @handle.stub!(:setsockopt)
-      ::Socket.stub!(:new).and_return(@handle)
+      @handle = double("Handle", :closed? => false)
+      allow(@handle).to receive(:close)
+      allow(@handle).to receive(:connect_nonblock)
+      allow(@handle).to receive(:setsockopt)
+      allow(::Socket).to receive(:new).and_return(@handle)
     end
 
     it_should_behave_like "a socket"
 
     it "should raise a TransportException when it cannot open a socket" do
-      ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
-      lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
+      expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
+      expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
     end
 
     it "should open a ::Socket with default args" do
-      ::Socket.should_receive(:new).and_return(mock("Handle", :connect_nonblock => true, :setsockopt => nil))
-      ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
-      ::Socket.should_receive(:sockaddr_in)
+      expect(::Socket).to receive(:new).and_return(double("Handle", :connect_nonblock => true, :setsockopt => nil))
+      expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
+      expect(::Socket).to receive(:sockaddr_in)
+      @socket.to_s == "socket(localhost:9090)"
       @socket.open
     end
 
     it "should accept host/port options" do
-      ::Socket.should_receive(:new).and_return(mock("Handle", :connect_nonblock => true, :setsockopt => nil))
-      ::Socket.should_receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
-      ::Socket.should_receive(:sockaddr_in)
-      Thrift::Socket.new('my.domain', 1234).open
+      expect(::Socket).to receive(:new).and_return(double("Handle", :connect_nonblock => true, :setsockopt => nil))
+      expect(::Socket).to receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
+      expect(::Socket).to receive(:sockaddr_in)
+      @socket = Thrift::Socket.new('my.domain', 1234).open
+      @socket.to_s == "socket(my.domain:1234)"
     end
 
     it "should accept an optional timeout" do
-      ::Socket.stub!(:new)
-      Thrift::Socket.new('localhost', 8080, 5).timeout.should == 5
+      allow(::Socket).to receive(:new)
+      expect(Thrift::Socket.new('localhost', 8080, 5).timeout).to eq(5)
+    end
+
+    it "should provide a reasonable to_s" do
+      allow(::Socket).to receive(:new)
+      expect(Thrift::Socket.new('myhost', 8090).to_s).to eq("socket(myhost:8090)")
     end
   end
 end
diff --git a/lib/rb/spec/socket_spec_shared.rb b/lib/rb/spec/socket_spec_shared.rb
index 5fddc16..32bdb71 100644
--- a/lib/rb/spec/socket_spec_shared.rb
+++ b/lib/rb/spec/socket_spec_shared.rb
@@ -21,84 +21,84 @@
 
 shared_examples_for "a socket" do
   it "should open a socket" do
-    @socket.open.should == @handle
+    expect(@socket.open).to eq(@handle)
   end
 
   it "should be open whenever it has a handle" do
-    @socket.should_not be_open
+    expect(@socket).not_to be_open
     @socket.open
-    @socket.should be_open
+    expect(@socket).to be_open
     @socket.handle = nil
-    @socket.should_not be_open
+    expect(@socket).not_to be_open
     @socket.handle = @handle
     @socket.close
-    @socket.should_not be_open
+    expect(@socket).not_to be_open
   end
 
   it "should write data to the handle" do
     @socket.open
-    @handle.should_receive(:write).with("foobar")
+    expect(@handle).to receive(:write).with("foobar")
     @socket.write("foobar")
-    @handle.should_receive(:write).with("fail").and_raise(StandardError)
-    lambda { @socket.write("fail") }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
+    expect(@handle).to receive(:write).with("fail").and_raise(StandardError)
+    expect { @socket.write("fail") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
   end
 
   it "should raise an error when it cannot read from the handle" do
     @socket.open
-    @handle.should_receive(:readpartial).with(17).and_raise(StandardError)
-    lambda { @socket.read(17) }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
+    expect(@handle).to receive(:readpartial).with(17).and_raise(StandardError)
+    expect { @socket.read(17) }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
   end
 
   it "should return the data read when reading from the handle works" do
     @socket.open
-    @handle.should_receive(:readpartial).with(17).and_return("test data")
-    @socket.read(17).should == "test data"
+    expect(@handle).to receive(:readpartial).with(17).and_return("test data")
+    expect(@socket.read(17)).to eq("test data")
   end
 
   it "should declare itself as closed when it has an error" do
     @socket.open
-    @handle.should_receive(:write).with("fail").and_raise(StandardError)
-    @socket.should be_open
-    lambda { @socket.write("fail") }.should raise_error
-    @socket.should_not be_open
+    expect(@handle).to receive(:write).with("fail").and_raise(StandardError)
+    expect(@socket).to be_open
+    expect { @socket.write("fail") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
+    expect(@socket).not_to be_open
   end
 
   it "should raise an error when the stream is closed" do
     @socket.open
-    @handle.stub!(:closed?).and_return(true)
-    @socket.should_not be_open
-    lambda { @socket.write("fail") }.should raise_error(IOError, "closed stream")
-    lambda { @socket.read(10) }.should raise_error(IOError, "closed stream")
+    allow(@handle).to receive(:closed?).and_return(true)
+    expect(@socket).not_to be_open
+    expect { @socket.write("fail") }.to raise_error(IOError, "closed stream")
+    expect { @socket.read(10) }.to raise_error(IOError, "closed stream")
   end
 
   it "should support the timeout accessor for read" do
     @socket.timeout = 3
     @socket.open
-    IO.should_receive(:select).with([@handle], nil, nil, 3).and_return([[@handle], [], []])
-    @handle.should_receive(:readpartial).with(17).and_return("test data")
-    @socket.read(17).should == "test data"
+    expect(IO).to receive(:select).with([@handle], nil, nil, 3).and_return([[@handle], [], []])
+    expect(@handle).to receive(:readpartial).with(17).and_return("test data")
+    expect(@socket.read(17)).to eq("test data")
   end
 
   it "should support the timeout accessor for write" do
     @socket.timeout = 3
     @socket.open
-    IO.should_receive(:select).with(nil, [@handle], nil, 3).twice.and_return([[], [@handle], []])
-    @handle.should_receive(:write_nonblock).with("test data").and_return(4)
-    @handle.should_receive(:write_nonblock).with(" data").and_return(5)
-    @socket.write("test data").should == 9
+    expect(IO).to receive(:select).with(nil, [@handle], nil, 3).twice.and_return([[], [@handle], []])
+    expect(@handle).to receive(:write_nonblock).with("test data").and_return(4)
+    expect(@handle).to receive(:write_nonblock).with(" data").and_return(5)
+    expect(@socket.write("test data")).to eq(9)
   end
 
   it "should raise an error when read times out" do
     @socket.timeout = 0.5
     @socket.open
-    IO.should_receive(:select).once {sleep(0.5); nil}
-    lambda { @socket.read(17) }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::TIMED_OUT }
+    expect(IO).to receive(:select).once {sleep(0.5); nil}
+    expect { @socket.read(17) }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) }
   end
 
   it "should raise an error when write times out" do
     @socket.timeout = 0.5
     @socket.open
-    IO.should_receive(:select).with(nil, [@handle], nil, 0.5).any_number_of_times.and_return(nil)
-    lambda { @socket.write("test data") }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::TIMED_OUT }
+    allow(IO).to receive(:select).with(nil, [@handle], nil, 0.5).and_return(nil)
+    expect { @socket.write("test data") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) }
   end
 end
diff --git a/lib/rb/spec/ssl_server_socket_spec.rb b/lib/rb/spec/ssl_server_socket_spec.rb
new file mode 100644
index 0000000..82e6518
--- /dev/null
+++ b/lib/rb/spec/ssl_server_socket_spec.rb
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+require 'spec_helper'
+require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared")
+
+describe 'SSLServerSocket' do
+
+  describe Thrift::SSLServerSocket do
+    before(:each) do
+      @socket = Thrift::SSLServerSocket.new(1234)
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(@socket.to_s).to eq("ssl(socket(:1234))")
+    end
+  end
+end
diff --git a/lib/rb/spec/ssl_socket_spec.rb b/lib/rb/spec/ssl_socket_spec.rb
index a8bc785..808d8d5 100644
--- a/lib/rb/spec/ssl_socket_spec.rb
+++ b/lib/rb/spec/ssl_socket_spec.rb
@@ -26,49 +26,53 @@
     before(:each) do
       @context = OpenSSL::SSL::SSLContext.new
       @socket = Thrift::SSLSocket.new
-      @simple_socket_handle = mock("Handle", :closed? => false)
-      @simple_socket_handle.stub!(:close)
-      @simple_socket_handle.stub!(:connect_nonblock)
-      @simple_socket_handle.stub!(:setsockopt)
+      @simple_socket_handle = double("Handle", :closed? => false)
+      allow(@simple_socket_handle).to receive(:close)
+      allow(@simple_socket_handle).to receive(:connect_nonblock)
+      allow(@simple_socket_handle).to receive(:setsockopt)
 
-      @handle = mock(mock("SSLHandle", :connect_nonblock => true, :post_connection_check => true), :closed? => false)
-      @handle.stub!(:connect_nonblock)
-      @handle.stub!(:close)
-      @handle.stub!(:post_connection_check)
+      @handle = double(double("SSLHandle", :connect_nonblock => true, :post_connection_check => true), :closed? => false)
+      allow(@handle).to receive(:connect_nonblock)
+      allow(@handle).to receive(:close)
+      allow(@handle).to receive(:post_connection_check)
 
-      ::Socket.stub!(:new).and_return(@simple_socket_handle)
-      OpenSSL::SSL::SSLSocket.stub!(:new).and_return(@handle)
+      allow(::Socket).to receive(:new).and_return(@simple_socket_handle)
+      allow(OpenSSL::SSL::SSLSocket).to receive(:new).and_return(@handle)
     end
 
     it_should_behave_like "a socket"
 
     it "should raise a TransportException when it cannot open a ssl socket" do
-      ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
-      lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
+      expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
+      expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
     end
 
     it "should open a ::Socket with default args" do
-      OpenSSL::SSL::SSLSocket.should_receive(:new).with(@simple_socket_handle, nil).and_return(@handle)
-      @handle.should_receive(:post_connection_check).with('localhost')
+      expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(@simple_socket_handle, nil).and_return(@handle)
+      expect(@handle).to receive(:post_connection_check).with('localhost')
       @socket.open
     end
 
     it "should accept host/port options" do
-      handle = mock("Handle", :connect_nonblock => true, :setsockopt => nil)
-      ::Socket.stub!(:new).and_return(handle)
-      ::Socket.should_receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
-      ::Socket.should_receive(:sockaddr_in)
-      OpenSSL::SSL::SSLSocket.should_receive(:new).with(handle, nil).and_return(@handle)
-      @handle.should_receive(:post_connection_check).with('my.domain')
+      handle = double("Handle", :connect_nonblock => true, :setsockopt => nil)
+      allow(::Socket).to receive(:new).and_return(handle)
+      expect(::Socket).to receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
+      expect(::Socket).to receive(:sockaddr_in)
+      expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(handle, nil).and_return(@handle)
+      expect(@handle).to receive(:post_connection_check).with('my.domain')
       Thrift::SSLSocket.new('my.domain', 1234, 6000, nil).open
     end
 
     it "should accept an optional timeout" do
-      Thrift::SSLSocket.new('localhost', 8080, 5).timeout.should == 5
+      expect(Thrift::SSLSocket.new('localhost', 8080, 5).timeout).to eq(5)
     end
 
     it "should accept an optional context" do
-      Thrift::SSLSocket.new('localhost', 8080, 5, @context).ssl_context.should == @context
+      expect(Thrift::SSLSocket.new('localhost', 8080, 5, @context).ssl_context).to eq(@context)
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(Thrift::SSLSocket.new('myhost', 8090).to_s).to eq("ssl(socket(myhost:8090))")
     end
   end
 end
diff --git a/lib/rb/spec/struct_nested_containers_spec.rb b/lib/rb/spec/struct_nested_containers_spec.rb
index dc8ce5f..d063569 100644
--- a/lib/rb/spec/struct_nested_containers_spec.rb
+++ b/lib/rb/spec/struct_nested_containers_spec.rb
@@ -39,9 +39,9 @@
           thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ]
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.push [3, 4, 5]
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -52,9 +52,9 @@
           thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ].to_set
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.add [3, 4, 5]
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -65,9 +65,9 @@
           thrift_struct.value = { [1, 2, 3] => 1, [2, 3, 4] => 2 }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[[3, 4, 5]] = 3
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -78,9 +78,9 @@
           thrift_struct.value = { 1 => [1, 2, 3], 2 => [2, 3, 4] }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[3] = [3, 4, 5]
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -91,9 +91,9 @@
           thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ]
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.push([3, 4, 5].to_set)
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -104,9 +104,9 @@
           thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ].to_set
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.add([3, 4, 5].to_set)
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -117,9 +117,9 @@
           thrift_struct.value = { [1, 2, 3].to_set => 1, [2, 3, 4].to_set => 2 }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[[3, 4, 5].to_set] = 3
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -130,9 +130,9 @@
           thrift_struct.value = { 1 => [1, 2, 3].to_set, 2 => [2, 3, 4].to_set }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[3] = [3, 4, 5].to_set
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -143,9 +143,9 @@
           thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ]
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.push({ 3 => 4, 5 => 6 })
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -156,9 +156,9 @@
           thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ].to_set
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value.add({ 3 => 4, 5 => 6 })
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -169,9 +169,9 @@
           thrift_struct.value = { { 1 => 2, 3 => 4} => 1, {2 => 3, 4 => 5}  => 2 }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[{3 => 4, 5 => 6}] = 3
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
 
@@ -182,9 +182,9 @@
           thrift_struct.value = { 1 => { 1 => 2, 3 => 4}, 2 => {2 => 3, 4 => 5} }
           thrift_struct.validate
         end
-        a.should == b
+        expect(a).to eq(b)
         b.value[3] = { 3 => 4, 5 => 6 }
-        a.should_not == b
+        expect(a).not_to eq(b)
       end
     end
   end
diff --git a/lib/rb/spec/struct_spec.rb b/lib/rb/spec/struct_spec.rb
index 6534d61..bbd502b 100644
--- a/lib/rb/spec/struct_spec.rb
+++ b/lib/rb/spec/struct_spec.rb
@@ -25,7 +25,7 @@
     it "should iterate over all fields properly" do
       fields = {}
       SpecNamespace::Foo.new.each_field { |fid,field_info| fields[fid] = field_info }
-      fields.should == SpecNamespace::Foo::FIELDS
+      expect(fields).to eq(SpecNamespace::Foo::FIELDS)
     end
 
     it "should initialize all fields to defaults" do
@@ -39,19 +39,19 @@
     end
 
     def validate_default_arguments(object)
-      object.simple.should == 53
-      object.words.should == "words"
-      object.hello.should == SpecNamespace::Hello.new(:greeting => 'hello, world!')
-      object.ints.should == [1, 2, 2, 3]
-      object.complex.should be_nil
-      object.shorts.should == Set.new([5, 17, 239])
+      expect(object.simple).to eq(53)
+      expect(object.words).to eq("words")
+      expect(object.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!'))
+      expect(object.ints).to eq([1, 2, 2, 3])
+      expect(object.complex).to be_nil
+      expect(object.shorts).to eq(Set.new([5, 17, 239]))
     end
 
     it "should not share default values between instances" do
       begin
         struct = SpecNamespace::Foo.new
         struct.ints << 17
-        SpecNamespace::Foo.new.ints.should == [1,2,2,3]
+        expect(SpecNamespace::Foo.new.ints).to eq([1,2,2,3])
       ensure
         # ensure no leakage to other tests
         SpecNamespace::Foo::FIELDS[4][:default] = [1,2,2,3]
@@ -60,48 +60,48 @@
 
     it "should properly initialize boolean values" do
       struct = SpecNamespace::BoolStruct.new(:yesno => false)
-      struct.yesno.should be_false
+      expect(struct.yesno).to be_falsey
     end
 
     it "should have proper == semantics" do
-      SpecNamespace::Foo.new.should_not == SpecNamespace::Hello.new
-      SpecNamespace::Foo.new.should == SpecNamespace::Foo.new
-      SpecNamespace::Foo.new(:simple => 52).should_not == SpecNamespace::Foo.new
+      expect(SpecNamespace::Foo.new).not_to eq(SpecNamespace::Hello.new)
+      expect(SpecNamespace::Foo.new).to eq(SpecNamespace::Foo.new)
+      expect(SpecNamespace::Foo.new(:simple => 52)).not_to eq(SpecNamespace::Foo.new)
     end
 
     it "should print enum value names in inspect" do
-      SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect.should == "<SpecNamespace::StructWithSomeEnum some_enum:ONE (0)>"
+      expect(SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("<SpecNamespace::StructWithSomeEnum some_enum:ONE (0)>")
 
-      SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect.should == "<SpecNamespace::StructWithEnumMap my_map:{ONE (0): [TWO (1)]}>"
+      expect(SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("<SpecNamespace::StructWithEnumMap my_map:{ONE (0): [TWO (1)]}>")
     end
 
     it "should pretty print binary fields" do
-      SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect.should == "<SpecNamespace::Foo2 my_binary:010203>"
+      expect(SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect).to eq("<SpecNamespace::Foo2 my_binary:010203>")
     end
 
     it "should offer field? methods" do
-      SpecNamespace::Foo.new.opt_string?.should be_false
-      SpecNamespace::Foo.new(:simple => 52).simple?.should be_true
-      SpecNamespace::Foo.new(:my_bool => false).my_bool?.should be_true
-      SpecNamespace::Foo.new(:my_bool => true).my_bool?.should be_true
+      expect(SpecNamespace::Foo.new.opt_string?).to be_falsey
+      expect(SpecNamespace::Foo.new(:simple => 52).simple?).to be_truthy
+      expect(SpecNamespace::Foo.new(:my_bool => false).my_bool?).to be_truthy
+      expect(SpecNamespace::Foo.new(:my_bool => true).my_bool?).to be_truthy
     end
 
     it "should be comparable" do
       s1 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE)
       s2 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::TWO)
 
-      (s1 <=> s2).should == -1
-      (s2 <=> s1).should == 1
-      (s1 <=> s1).should == 0
-      (s1 <=> SpecNamespace::StructWithSomeEnum.new()).should == -1
+      expect(s1 <=> s2).to eq(-1)
+      expect(s2 <=> s1).to eq(1)
+      expect(s1 <=> s1).to eq(0)
+      expect(s1 <=> SpecNamespace::StructWithSomeEnum.new()).to eq(-1)
     end
 
     it "should read itself off the wire" do
       struct = SpecNamespace::Foo.new
-      prot = Thrift::BaseProtocol.new(mock("transport"))
-      prot.should_receive(:read_struct_begin).twice
-      prot.should_receive(:read_struct_end).twice
-      prot.should_receive(:read_field_begin).and_return(
+      prot = Thrift::BaseProtocol.new(double("transport"))
+      expect(prot).to receive(:read_struct_begin).twice
+      expect(prot).to receive(:read_struct_end).twice
+      expect(prot).to receive(:read_field_begin).and_return(
         ['complex', Thrift::Types::MAP, 5], # Foo
         ['words', Thrift::Types::STRING, 2], # Foo
         ['hello', Thrift::Types::STRUCT, 3], # Foo
@@ -112,49 +112,49 @@
         ['shorts', Thrift::Types::SET, 6], # Foo
         [nil, Thrift::Types::STOP, 0] # Hello
       )
-      prot.should_receive(:read_field_end).exactly(7).times
-      prot.should_receive(:read_map_begin).and_return(
+      expect(prot).to receive(:read_field_end).exactly(7).times
+      expect(prot).to receive(:read_map_begin).and_return(
         [Thrift::Types::I32, Thrift::Types::MAP, 2], # complex
           [Thrift::Types::STRING, Thrift::Types::DOUBLE, 2], # complex/1/value
           [Thrift::Types::STRING, Thrift::Types::DOUBLE, 1] # complex/2/value
       )
-      prot.should_receive(:read_map_end).exactly(3).times
-      prot.should_receive(:read_list_begin).and_return([Thrift::Types::I32, 4])
-      prot.should_receive(:read_list_end)
-      prot.should_receive(:read_set_begin).and_return([Thrift::Types::I16, 2])
-      prot.should_receive(:read_set_end)
-      prot.should_receive(:read_i32).and_return(
+      expect(prot).to receive(:read_map_end).exactly(3).times
+      expect(prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, 4])
+      expect(prot).to receive(:read_list_end)
+      expect(prot).to receive(:read_set_begin).and_return([Thrift::Types::I16, 2])
+      expect(prot).to receive(:read_set_end)
+      expect(prot).to receive(:read_i32).and_return(
         1, 14,        # complex keys
         42,           # simple
         4, 23, 4, 29  # ints
       )
-      prot.should_receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
-      prot.should_receive(:read_double).and_return(Math::PI, Math::E, 4.669201609)
-      prot.should_receive(:read_i16).and_return(2, 3)
-      prot.should_not_receive(:skip)
+      expect(prot).to receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
+      expect(prot).to receive(:read_double).and_return(Math::PI, Math::E, 4.669201609)
+      expect(prot).to receive(:read_i16).and_return(2, 3)
+      expect(prot).not_to receive(:skip)
       struct.read(prot)
 
-      struct.simple.should == 42
-      struct.complex.should == {1 => {"pi" => Math::PI, "e" => Math::E}, 14 => {"feigenbaum" => 4.669201609}}
-      struct.hello.should == SpecNamespace::Hello.new(:greeting => "what's up?")
-      struct.words.should == "apple banana"
-      struct.ints.should == [4, 23, 4, 29]
-      struct.shorts.should == Set.new([3, 2])
+      expect(struct.simple).to eq(42)
+      expect(struct.complex).to eq({1 => {"pi" => Math::PI, "e" => Math::E}, 14 => {"feigenbaum" => 4.669201609}})
+      expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => "what's up?"))
+      expect(struct.words).to eq("apple banana")
+      expect(struct.ints).to eq([4, 23, 4, 29])
+      expect(struct.shorts).to eq(Set.new([3, 2]))
     end
 
     it "should serialize false boolean fields correctly" do
       b = SpecNamespace::BoolStruct.new(:yesno => false)
       prot = Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new)
-      prot.should_receive(:write_bool).with(false)
+      expect(prot).to receive(:write_bool).with(false)
       b.write(prot)
     end
 
     it "should skip unexpected fields in structs and use default values" do
       struct = SpecNamespace::Foo.new
-      prot = Thrift::BaseProtocol.new(mock("transport"))
-      prot.should_receive(:read_struct_begin)
-      prot.should_receive(:read_struct_end)
-      prot.should_receive(:read_field_begin).and_return(
+      prot = Thrift::BaseProtocol.new(double("transport"))
+      expect(prot).to receive(:read_struct_begin)
+      expect(prot).to receive(:read_struct_end)
+      expect(prot).to receive(:read_field_begin).and_return(
         ['simple', Thrift::Types::I32, 1],
         ['complex', Thrift::Types::STRUCT, 5],
         ['thinz', Thrift::Types::MAP, 7],
@@ -162,55 +162,55 @@
         ['words', Thrift::Types::STRING, 2],
         [nil, Thrift::Types::STOP, 0]
       )
-      prot.should_receive(:read_field_end).exactly(5).times
-      prot.should_receive(:read_i32).and_return(42)
-      prot.should_receive(:read_string).and_return("foobar")
-      prot.should_receive(:skip).with(Thrift::Types::STRUCT)
-      prot.should_receive(:skip).with(Thrift::Types::MAP)
+      expect(prot).to receive(:read_field_end).exactly(5).times
+      expect(prot).to receive(:read_i32).and_return(42)
+      expect(prot).to receive(:read_string).and_return("foobar")
+      expect(prot).to receive(:skip).with(Thrift::Types::STRUCT)
+      expect(prot).to receive(:skip).with(Thrift::Types::MAP)
       # prot.should_receive(:read_map_begin).and_return([Thrift::Types::I32, Thrift::Types::I32, 0])
       # prot.should_receive(:read_map_end)
-      prot.should_receive(:skip).with(Thrift::Types::I32)
+      expect(prot).to receive(:skip).with(Thrift::Types::I32)
       struct.read(prot)
 
-      struct.simple.should == 42
-      struct.complex.should be_nil
-      struct.words.should == "foobar"
-      struct.hello.should == SpecNamespace::Hello.new(:greeting => 'hello, world!')
-      struct.ints.should == [1, 2, 2, 3]
-      struct.shorts.should == Set.new([5, 17, 239])
+      expect(struct.simple).to eq(42)
+      expect(struct.complex).to be_nil
+      expect(struct.words).to eq("foobar")
+      expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!'))
+      expect(struct.ints).to eq([1, 2, 2, 3])
+      expect(struct.shorts).to eq(Set.new([5, 17, 239]))
     end
 
     it "should write itself to the wire" do
-      prot = Thrift::BaseProtocol.new(mock("transport")) #mock("Protocol")
-      prot.should_receive(:write_struct_begin).with("SpecNamespace::Foo")
-      prot.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
-      prot.should_receive(:write_struct_end).twice
-      prot.should_receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4)
-      prot.should_receive(:write_i32).with(1)
-      prot.should_receive(:write_i32).with(2).twice
-      prot.should_receive(:write_i32).with(3)
-      prot.should_receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5)
-      prot.should_receive(:write_i32).with(5)
-      prot.should_receive(:write_string).with('foo')
-      prot.should_receive(:write_double).with(1.23)
-      prot.should_receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6)
-      prot.should_receive(:write_i16).with(5)
-      prot.should_receive(:write_i16).with(17)
-      prot.should_receive(:write_i16).with(239)
-      prot.should_receive(:write_field_stop).twice
-      prot.should_receive(:write_field_end).exactly(6).times
-      prot.should_receive(:write_field_begin).with('simple', Thrift::Types::I32, 1)
-      prot.should_receive(:write_i32).with(53)
-      prot.should_receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3)
-      prot.should_receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1)
-      prot.should_receive(:write_string).with('hello, world!')
-      prot.should_receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1)
-      prot.should_receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1)
-      prot.should_receive(:write_map_end).twice
-      prot.should_receive(:write_list_begin).with(Thrift::Types::I32, 4)
-      prot.should_receive(:write_list_end)
-      prot.should_receive(:write_set_begin).with(Thrift::Types::I16, 3)
-      prot.should_receive(:write_set_end)
+      prot = Thrift::BaseProtocol.new(double("transport")) #mock("Protocol")
+      expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Foo")
+      expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Hello")
+      expect(prot).to receive(:write_struct_end).twice
+      expect(prot).to receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4)
+      expect(prot).to receive(:write_i32).with(1)
+      expect(prot).to receive(:write_i32).with(2).twice
+      expect(prot).to receive(:write_i32).with(3)
+      expect(prot).to receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5)
+      expect(prot).to receive(:write_i32).with(5)
+      expect(prot).to receive(:write_string).with('foo')
+      expect(prot).to receive(:write_double).with(1.23)
+      expect(prot).to receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6)
+      expect(prot).to receive(:write_i16).with(5)
+      expect(prot).to receive(:write_i16).with(17)
+      expect(prot).to receive(:write_i16).with(239)
+      expect(prot).to receive(:write_field_stop).twice
+      expect(prot).to receive(:write_field_end).exactly(6).times
+      expect(prot).to receive(:write_field_begin).with('simple', Thrift::Types::I32, 1)
+      expect(prot).to receive(:write_i32).with(53)
+      expect(prot).to receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3)
+      expect(prot).to receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1)
+      expect(prot).to receive(:write_string).with('hello, world!')
+      expect(prot).to receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1)
+      expect(prot).to receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1)
+      expect(prot).to receive(:write_map_end).twice
+      expect(prot).to receive(:write_list_begin).with(Thrift::Types::I32, 4)
+      expect(prot).to receive(:write_list_end)
+      expect(prot).to receive(:write_set_begin).with(Thrift::Types::I16, 3)
+      expect(prot).to receive(:write_set_end)
 
       struct = SpecNamespace::Foo.new
       struct.words = nil
@@ -221,50 +221,50 @@
     it "should raise an exception if presented with an unknown container" do
       # yeah this is silly, but I'm going for code coverage here
       struct = SpecNamespace::Foo.new
-      lambda { struct.send :write_container, nil, nil, {:type => "foo"} }.should raise_error(StandardError, "Not a container type: foo")
+      expect { struct.send :write_container, nil, nil, {:type => "foo"} }.to raise_error(StandardError, "Not a container type: foo")
     end
 
     it "should support optional type-checking in Thrift::Struct.new" do
       Thrift.type_checking = true
       begin
-        lambda { SpecNamespace::Hello.new(:greeting => 3) }.should raise_error(Thrift::TypeError, "Expected Types::STRING, received Fixnum for field greeting")
+        expect { SpecNamespace::Hello.new(:greeting => 3) }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/)
       ensure
         Thrift.type_checking = false
       end
-      lambda { SpecNamespace::Hello.new(:greeting => 3) }.should_not raise_error(Thrift::TypeError)
+      expect { SpecNamespace::Hello.new(:greeting => 3) }.not_to raise_error
     end
 
     it "should support optional type-checking in field accessors" do
       Thrift.type_checking = true
       begin
         hello = SpecNamespace::Hello.new
-        lambda { hello.greeting = 3 }.should raise_error(Thrift::TypeError, "Expected Types::STRING, received Fixnum for field greeting")
+        expect { hello.greeting = 3 }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/)
       ensure
         Thrift.type_checking = false
       end
-      lambda { hello.greeting = 3 }.should_not raise_error(Thrift::TypeError)
+      expect { hello.greeting = 3 }.not_to raise_error
     end
 
     it "should raise an exception when unknown types are given to Thrift::Struct.new" do
-      lambda { SpecNamespace::Hello.new(:fish => 'salmon') }.should raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
+      expect { SpecNamespace::Hello.new(:fish => 'salmon') }.to raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
     end
 
     it "should support `raise Xception, 'message'` for Exception structs" do
       begin
         raise SpecNamespace::Xception, "something happened"
       rescue Thrift::Exception => e
-        e.message.should == "something happened"
-        e.code.should == 1
+        expect(e.message).to eq("something happened")
+        expect(e.code).to eq(1)
         # ensure it gets serialized properly, this is the really important part
-        prot = Thrift::BaseProtocol.new(mock("trans"))
-        prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
-        prot.should_receive(:write_struct_end)
-        prot.should_receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)#, "something happened")
-        prot.should_receive(:write_string).with("something happened")
-        prot.should_receive(:write_field_begin).with('code', Thrift::Types::I32, 2)#, 1)
-        prot.should_receive(:write_i32).with(1)
-        prot.should_receive(:write_field_stop)
-        prot.should_receive(:write_field_end).twice
+        prot = Thrift::BaseProtocol.new(double("trans"))
+        expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
+        expect(prot).to receive(:write_struct_end)
+        expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)#, "something happened")
+        expect(prot).to receive(:write_string).with("something happened")
+        expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)#, 1)
+        expect(prot).to receive(:write_i32).with(1)
+        expect(prot).to receive(:write_field_stop)
+        expect(prot).to receive(:write_field_end).twice
 
         e.write(prot)
       end
@@ -274,17 +274,17 @@
       begin
         raise SpecNamespace::Xception, :message => "something happened", :code => 5
       rescue Thrift::Exception => e
-        e.message.should == "something happened"
-        e.code.should == 5
-        prot = Thrift::BaseProtocol.new(mock("trans"))
-        prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
-        prot.should_receive(:write_struct_end)
-        prot.should_receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
-        prot.should_receive(:write_string).with("something happened")
-        prot.should_receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
-        prot.should_receive(:write_i32).with(5)
-        prot.should_receive(:write_field_stop)
-        prot.should_receive(:write_field_end).twice
+        expect(e.message).to eq("something happened")
+        expect(e.code).to eq(5)
+        prot = Thrift::BaseProtocol.new(double("trans"))
+        expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
+        expect(prot).to receive(:write_struct_end)
+        expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
+        expect(prot).to receive(:write_string).with("something happened")
+        expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
+        expect(prot).to receive(:write_i32).with(5)
+        expect(prot).to receive(:write_field_stop)
+        expect(prot).to receive(:write_field_end).twice
 
         e.write(prot)
       end
diff --git a/lib/rb/spec/thin_http_server_spec.rb b/lib/rb/spec/thin_http_server_spec.rb
index 5520839..665391b 100644
--- a/lib/rb/spec/thin_http_server_spec.rb
+++ b/lib/rb/spec/thin_http_server_spec.rb
@@ -23,24 +23,24 @@
 
 describe Thrift::ThinHTTPServer do
 
-  let(:processor) { mock('processor') }
+  let(:processor) { double('processor') }
 
   describe "#initialize" do
 
     context "when using the defaults" do
 
       it "binds to port 80, with host 0.0.0.0, a path of '/'" do
-        Thin::Server.should_receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder))
+        expect(Thin::Server).to receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder))
         Thrift::ThinHTTPServer.new(processor)
       end
 
       it 'creates a ThinHTTPServer::RackApplicationContext' do
-        Thrift::ThinHTTPServer::RackApplication.should_receive(:for).with("/", processor, an_instance_of(Thrift::BinaryProtocolFactory)).and_return(anything)
+        expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::BinaryProtocolFactory)).and_return(anything)
         Thrift::ThinHTTPServer.new(processor)
       end
 
       it "uses the BinaryProtocolFactory" do
-        Thrift::BinaryProtocolFactory.should_receive(:new)
+        expect(Thrift::BinaryProtocolFactory).to receive(:new)
         Thrift::ThinHTTPServer.new(processor)
       end
 
@@ -52,7 +52,7 @@
         ip = "192.168.0.1"
         port = 3000
         path = "/thin"
-        Thin::Server.should_receive(:new).with(ip, port, an_instance_of(Rack::Builder))
+        expect(Thin::Server).to receive(:new).with(ip, port, an_instance_of(Rack::Builder))
         Thrift::ThinHTTPServer.new(processor,
                            :ip => ip,
                            :port => port,
@@ -60,7 +60,7 @@
       end
 
       it 'creates a ThinHTTPServer::RackApplicationContext with a different protocol factory' do
-        Thrift::ThinHTTPServer::RackApplication.should_receive(:for).with("/", processor, an_instance_of(Thrift::JsonProtocolFactory)).and_return(anything)
+        expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::JsonProtocolFactory)).and_return(anything)
         Thrift::ThinHTTPServer.new(processor,
                            :protocol_factory => Thrift::JsonProtocolFactory.new)
       end
@@ -72,12 +72,12 @@
   describe "#serve" do
 
     it 'starts the Thin server' do
-      underlying_thin_server = mock('thin server', :start => true)
-      Thin::Server.stub(:new).and_return(underlying_thin_server)
+      underlying_thin_server = double('thin server', :start => true)
+      allow(Thin::Server).to receive(:new).and_return(underlying_thin_server)
 
       thin_thrift_server = Thrift::ThinHTTPServer.new(processor)
 
-      underlying_thin_server.should_receive(:start)
+      expect(underlying_thin_server).to receive(:start)
       thin_thrift_server.serve
     end
   end
@@ -87,8 +87,8 @@
 describe Thrift::ThinHTTPServer::RackApplication do
   include Rack::Test::Methods
 
-  let(:processor) { mock('processor') }
-  let(:protocol_factory) { mock('protocol factory') }
+  let(:processor) { double('processor') }
+  let(:protocol_factory) { double('protocol factory') }
 
   def app
     Thrift::ThinHTTPServer::RackApplication.for("/", processor, protocol_factory)
@@ -99,13 +99,13 @@
     it 'receives a non-POST' do
       header('Content-Type', "application/x-thrift")
       get "/"
-      last_response.status.should be 404
+      expect(last_response.status).to be 404
     end
 
     it 'receives a header other than application/x-thrift' do
       header('Content-Type', "application/json")
       post "/"
-      last_response.status.should be 404
+      expect(last_response.status).to be 404
     end
 
   end
@@ -113,26 +113,26 @@
   context "200 response" do
 
     before do
-      protocol_factory.stub(:get_protocol)
-      processor.stub(:process)
+      allow(protocol_factory).to receive(:get_protocol)
+      allow(processor).to receive(:process)
     end
 
     it 'creates an IOStreamTransport' do
       header('Content-Type', "application/x-thrift")
-      Thrift::IOStreamTransport.should_receive(:new).with(an_instance_of(Rack::Lint::InputWrapper), an_instance_of(Rack::Response))
+      expect(Thrift::IOStreamTransport).to receive(:new).with(an_instance_of(Rack::Lint::InputWrapper), an_instance_of(Rack::Response))
       post "/"
     end
 
     it 'fetches the right protocol based on the Transport' do
       header('Content-Type', "application/x-thrift")
-      protocol_factory.should_receive(:get_protocol).with(an_instance_of(Thrift::IOStreamTransport))
+      expect(protocol_factory).to receive(:get_protocol).with(an_instance_of(Thrift::IOStreamTransport))
       post "/"
     end
 
     it 'status code 200' do
       header('Content-Type', "application/x-thrift")
       post "/"
-      last_response.ok?.should be_true
+      expect(last_response.ok?).to be_truthy
     end
 
   end
diff --git a/lib/rb/spec/types_spec.rb b/lib/rb/spec/types_spec.rb
index b2c3a20..d595ab5 100644
--- a/lib/rb/spec/types_spec.rb
+++ b/lib/rb/spec/types_spec.rb
@@ -31,85 +31,88 @@
 
   context 'type checking' do
     it "should return the proper name for each type" do
-      Thrift.type_name(Thrift::Types::I16).should == "Types::I16"
-      Thrift.type_name(Thrift::Types::VOID).should == "Types::VOID"
-      Thrift.type_name(Thrift::Types::LIST).should == "Types::LIST"
-      Thrift.type_name(42).should be_nil
+      expect(Thrift.type_name(Thrift::Types::I16)).to eq("Types::I16")
+      expect(Thrift.type_name(Thrift::Types::VOID)).to eq("Types::VOID")
+      expect(Thrift.type_name(Thrift::Types::LIST)).to eq("Types::LIST")
+      expect(Thrift.type_name(42)).to be_nil
     end
 
     it "should check types properly" do
       # lambda { Thrift.check_type(nil, Thrift::Types::STOP) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3,              {:type => Thrift::Types::STOP},   :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil,            {:type => Thrift::Types::VOID},   :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3,              {:type => Thrift::Types::VOID},   :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(true,           {:type => Thrift::Types::BOOL},   :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3,              {:type => Thrift::Types::BOOL},   :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(42,             {:type => Thrift::Types::BYTE},   :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(42,             {:type => Thrift::Types::I16},    :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(42,             {:type => Thrift::Types::I32},    :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(42,             {:type => Thrift::Types::I64},    :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3.14,           {:type => Thrift::Types::I32},    :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3.14,           {:type => Thrift::Types::DOUBLE}, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3,              {:type => Thrift::Types::DOUBLE}, :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type("3",            {:type => Thrift::Types::STRING}, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(3,              {:type => Thrift::Types::STRING}, :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(3,              {:type => Thrift::Types::STOP},   :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil,            {:type => Thrift::Types::VOID},   :foo) }.not_to raise_error
+      expect { Thrift.check_type(3,              {:type => Thrift::Types::VOID},   :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(true,           {:type => Thrift::Types::BOOL},   :foo) }.not_to raise_error
+      expect { Thrift.check_type(3,              {:type => Thrift::Types::BOOL},   :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(42,             {:type => Thrift::Types::BYTE},   :foo) }.not_to raise_error
+      expect { Thrift.check_type(42,             {:type => Thrift::Types::I16},    :foo) }.not_to raise_error
+      expect { Thrift.check_type(42,             {:type => Thrift::Types::I32},    :foo) }.not_to raise_error
+      expect { Thrift.check_type(42,             {:type => Thrift::Types::I64},    :foo) }.not_to raise_error
+      expect { Thrift.check_type(3.14,           {:type => Thrift::Types::I32},    :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(3.14,           {:type => Thrift::Types::DOUBLE}, :foo) }.not_to raise_error
+      expect { Thrift.check_type(3,              {:type => Thrift::Types::DOUBLE}, :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type("3",            {:type => Thrift::Types::STRING}, :foo) }.not_to raise_error
+      expect { Thrift.check_type(3,              {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError)
       hello = SpecNamespace::Hello.new
-      lambda { Thrift.check_type(hello,          {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello}, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type("foo",          {:type => Thrift::Types::STRUCT}, :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type({:foo => 1},    {:type => Thrift::Types::MAP},    :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type([1],            {:type => Thrift::Types::MAP},    :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type([1],            {:type => Thrift::Types::LIST},   :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type({:foo => 1},    {:type => Thrift::Types::LIST},   :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(Set.new([1,2]), {:type => Thrift::Types::SET},    :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type([1,2],          {:type => Thrift::Types::SET},    :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type({:foo => true}, {:type => Thrift::Types::SET},    :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(hello,          {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello}, :foo) }.not_to raise_error
+      expect { Thrift.check_type("foo",          {:type => Thrift::Types::STRUCT}, :foo) }.to raise_error(Thrift::TypeError)
+      field = {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRING}}
+      expect { Thrift.check_type({1 => "one"},   field,                            :foo) }.not_to raise_error
+      expect { Thrift.check_type([1],            field,                            :foo) }.to raise_error(Thrift::TypeError)
+      field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::I32}}
+      expect { Thrift.check_type([1],            field,                            :foo) }.not_to raise_error
+      expect { Thrift.check_type({:foo => 1},    field,                            :foo) }.to raise_error(Thrift::TypeError)
+      field = {:type => Thrift::Types::SET, :element => {:type => Thrift::Types::I32}}
+      expect { Thrift.check_type(Set.new([1,2]), field,                            :foo) }.not_to raise_error
+      expect { Thrift.check_type([1,2],          field,                            :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type({:foo => true}, field,                            :foo) }.to raise_error(Thrift::TypeError)
     end
 
     it "should error out if nil is passed and skip_types is false" do
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::BOOL},   :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::BYTE},   :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::I16},    :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::I32},    :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::I64},    :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::DOUBLE}, :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::STRING}, :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::STRUCT}, :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::LIST},   :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::SET},    :foo, false) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(nil, {:type => Thrift::Types::MAP},    :foo, false) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::BOOL},   :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::BYTE},   :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::I16},    :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::I32},    :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::I64},    :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::DOUBLE}, :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::STRING}, :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::STRUCT}, :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::LIST},   :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::SET},    :foo, false) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(nil, {:type => Thrift::Types::MAP},    :foo, false) }.to raise_error(Thrift::TypeError)
     end
 
     it "should check element types on containers" do
       field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::I32}}
-      lambda { Thrift.check_type([1, 2], field, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type([1, nil, 2], field, :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type([1, 2], field, :foo) }.not_to raise_error
+      expect { Thrift.check_type([1, nil, 2], field, :foo) }.to raise_error(Thrift::TypeError)
       field = {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRING}}
-      lambda { Thrift.check_type({1 => "one", 2 => "two"}, field, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type({1 => "one", nil => "nil"}, field, :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type({1 => nil, 2 => "two"}, field, :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type({1 => "one", 2 => "two"}, field, :foo) }.not_to raise_error
+      expect { Thrift.check_type({1 => "one", nil => "nil"}, field, :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type({1 => nil, 2 => "two"}, field, :foo) }.to raise_error(Thrift::TypeError)
       field = {:type => Thrift::Types::SET, :element => {:type => Thrift::Types::I32}}
-      lambda { Thrift.check_type(Set.new([1, 2]), field, :foo) }.should_not raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(Set.new([1, nil, 2]), field, :foo) }.should raise_error(Thrift::TypeError)
-      lambda { Thrift.check_type(Set.new([1, 2.3, 2]), field, :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(Set.new([1, 2]), field, :foo) }.not_to raise_error
+      expect { Thrift.check_type(Set.new([1, nil, 2]), field, :foo) }.to raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(Set.new([1, 2.3, 2]), field, :foo) }.to raise_error(Thrift::TypeError)
 
       field = {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello}
-      lambda { Thrift.check_type(SpecNamespace::BoolStruct, field, :foo) }.should raise_error(Thrift::TypeError)
+      expect { Thrift.check_type(SpecNamespace::BoolStruct, field, :foo) }.to raise_error(Thrift::TypeError)
     end
 
     it "should give the Thrift::TypeError a readable message" do
-      msg = "Expected Types::STRING, received Fixnum for field foo"
-      lambda { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.should raise_error(Thrift::TypeError, msg)
-      msg = "Expected Types::STRING, received Fixnum for field foo.element"
+      msg = /Expected Types::STRING, received (Integer|Fixnum) for field foo/
+      expect { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError, msg)
+      msg = /Expected Types::STRING, received (Integer|Fixnum) for field foo.element/
       field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::STRING}}
-      lambda { Thrift.check_type([3], field, :foo) }.should raise_error(Thrift::TypeError, msg)
+      expect { Thrift.check_type([3], field, :foo) }.to raise_error(Thrift::TypeError, msg)
       msg = "Expected Types::I32, received NilClass for field foo.element.key"
       field = {:type => Thrift::Types::LIST,
                :element => {:type => Thrift::Types::MAP,
                             :key => {:type => Thrift::Types::I32},
                             :value => {:type => Thrift::Types::I32}}}
-      lambda { Thrift.check_type([{nil => 3}], field, :foo) }.should raise_error(Thrift::TypeError, msg)
+      expect { Thrift.check_type([{nil => 3}], field, :foo) }.to raise_error(Thrift::TypeError, msg)
       msg = "Expected Types::I32, received NilClass for field foo.element.value"
-      lambda { Thrift.check_type([{1 => nil}], field, :foo) }.should raise_error(Thrift::TypeError, msg)
+      expect { Thrift.check_type([{1 => nil}], field, :foo) }.to raise_error(Thrift::TypeError, msg)
     end
   end
 end
diff --git a/lib/rb/spec/union_spec.rb b/lib/rb/spec/union_spec.rb
index 6ad3194..0ce6306 100644
--- a/lib/rb/spec/union_spec.rb
+++ b/lib/rb/spec/union_spec.rb
@@ -24,85 +24,85 @@
   describe Thrift::Union do
     it "should return nil value in unset union" do
       union = SpecNamespace::My_union.new
-      union.get_set_field.should == nil
-      union.get_value.should == nil
+      expect(union.get_set_field).to eq(nil)
+      expect(union.get_value).to eq(nil)
     end
 
     it "should set a field and be accessible through get_value and the named field accessor" do
       union = SpecNamespace::My_union.new
       union.integer32 = 25
-      union.get_set_field.should == :integer32
-      union.get_value.should == 25
-      union.integer32.should == 25
+      expect(union.get_set_field).to eq(:integer32)
+      expect(union.get_value).to eq(25)
+      expect(union.integer32).to eq(25)
     end
 
     it "should work correctly when instantiated with static field constructors" do
       union = SpecNamespace::My_union.integer32(5)
-      union.get_set_field.should == :integer32
-      union.integer32.should == 5
+      expect(union.get_set_field).to eq(:integer32)
+      expect(union.integer32).to eq(5)
     end
 
     it "should raise for wrong set field" do
       union = SpecNamespace::My_union.new
       union.integer32 = 25
-      lambda { union.some_characters }.should raise_error(RuntimeError, "some_characters is not union's set field.")
+      expect { union.some_characters }.to raise_error(RuntimeError, "some_characters is not union's set field.")
     end
 
     it "should raise for wrong set field when hash initialized and type checking is off" do
       Thrift.type_checking = false
       union = SpecNamespace::My_union.new({incorrect_field: :incorrect})
       example = lambda { Thrift::Serializer.new.serialize(union) }
-      example.should raise_error(RuntimeError, "set_field is not valid for this union!")
+      expect(example).to raise_error(RuntimeError, "set_field is not valid for this union!")
     end
 
     it "should not be equal to nil" do
       union = SpecNamespace::My_union.new
-      union.should_not == nil
+      expect(union).not_to eq(nil)
     end
 
     it "should not be equal with an empty String" do
       union = SpecNamespace::My_union.new
-      union.should_not == ''
+      expect(union).not_to eq('')
     end
 
     it "should not equate two different unions, i32 vs. string" do
       union = SpecNamespace::My_union.new(:integer32, 25)
       other_union = SpecNamespace::My_union.new(:some_characters, "blah!")
-      union.should_not == other_union
+      expect(union).not_to eq(other_union)
     end
 
     it "should properly reset setfield and setvalue" do
       union = SpecNamespace::My_union.new(:integer32, 25)
-      union.get_set_field.should == :integer32
+      expect(union.get_set_field).to eq(:integer32)
       union.some_characters = "blah!"
-      union.get_set_field.should == :some_characters
-      union.get_value.should == "blah!"
-      lambda { union.integer32 }.should raise_error(RuntimeError, "integer32 is not union's set field.")
+      expect(union.get_set_field).to eq(:some_characters)
+      expect(union.get_value).to eq("blah!")
+      expect { union.integer32 }.to raise_error(RuntimeError, "integer32 is not union's set field.")
     end
 
     it "should not equate two different unions with different values" do
       union = SpecNamespace::My_union.new(:integer32, 25)
       other_union = SpecNamespace::My_union.new(:integer32, 400)
-      union.should_not == other_union
+      expect(union).not_to eq(other_union)
     end
 
     it "should not equate two different unions with different fields" do
       union = SpecNamespace::My_union.new(:integer32, 25)
       other_union = SpecNamespace::My_union.new(:other_i32, 25)
-      union.should_not == other_union
+      expect(union).not_to eq(other_union)
     end
 
     it "should inspect properly" do
       union = SpecNamespace::My_union.new(:integer32, 25)
-      union.inspect.should == "<SpecNamespace::My_union integer32: 25>"
+      expect(union.inspect).to eq("<SpecNamespace::My_union integer32: 25>")
     end
 
     it "should not allow setting with instance_variable_set" do
       union = SpecNamespace::My_union.new(:integer32, 27)
       union.instance_variable_set(:@some_characters, "hallo!")
-      union.get_set_field.should == :integer32
-      union.get_value.should == 27
-      lambda { union.some_characters }.should raise_error(RuntimeError, "some_characters is not union's set field.")
+      expect(union.get_set_field).to eq(:integer32)
+      expect(union.get_value).to eq(27)
+      expect { union.some_characters }.to raise_error(RuntimeError, "some_characters is not union's set field.")
     end
 
     it "should serialize to binary correctly" do
@@ -114,7 +114,7 @@
 
       other_union = SpecNamespace::My_union.new(:integer32, 25)
       other_union.read(proto)
-      other_union.should == union
+      expect(other_union).to eq(union)
     end
 
     it "should serialize to json correctly" do
@@ -126,24 +126,24 @@
 
       other_union = SpecNamespace::My_union.new(:integer32, 25)
       other_union.read(proto)
-      other_union.should == union
+      expect(other_union).to eq(union)
     end
 
     it "should raise when validating unset union" do
       union = SpecNamespace::My_union.new
-      lambda { union.validate }.should raise_error(StandardError, "Union fields are not set.")
+      expect { union.validate }.to raise_error(StandardError, "Union fields are not set.")
 
       other_union = SpecNamespace::My_union.new(:integer32, 1)
-      lambda { other_union.validate }.should_not raise_error(StandardError, "Union fields are not set.")
+      expect { other_union.validate }.not_to raise_error
     end
 
     it "should validate an enum field properly" do
       union = SpecNamespace::TestUnion.new(:enum_field, 3)
-      union.get_set_field.should == :enum_field
-      lambda { union.validate }.should raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!")
+      expect(union.get_set_field).to eq(:enum_field)
+      expect { union.validate }.to raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!")
 
       other_union = SpecNamespace::TestUnion.new(:enum_field, 1)
-      lambda { other_union.validate }.should_not raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!")
+      expect { other_union.validate }.not_to raise_error
     end
 
     it "should properly serialize and match structs with a union" do
@@ -158,37 +158,37 @@
       other_union = SpecNamespace::My_union.new(:some_characters, "hello there")
       swu2 = SpecNamespace::Struct_with_union.new(:fun_union => other_union)
 
-      swu2.should_not == swu
+      expect(swu2).not_to eq(swu)
 
       swu2.read(proto)
-      swu2.should == swu
+      expect(swu2).to eq(swu)
     end
 
     it "should support old style constructor" do
       union = SpecNamespace::My_union.new(:integer32 => 26)
-      union.get_set_field.should == :integer32
-      union.get_value.should == 26
+      expect(union.get_set_field).to eq(:integer32)
+      expect(union.get_value).to eq(26)
     end
 
     it "should not throw an error when inspected and unset" do
-      lambda{SpecNamespace::TestUnion.new().inspect}.should_not raise_error
+      expect{SpecNamespace::TestUnion.new().inspect}.not_to raise_error
     end
 
     it "should print enum value name when inspected" do
-      SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect.should == "<SpecNamespace::My_union some_enum: ONE (0)>"
+      expect(SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("<SpecNamespace::My_union some_enum: ONE (0)>")
 
-      SpecNamespace::My_union.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect.should == "<SpecNamespace::My_union my_map: {ONE (0): [TWO (1)]}>"
+      expect(SpecNamespace::My_union.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("<SpecNamespace::My_union my_map: {ONE (0): [TWO (1)]}>")
     end
 
     it "should offer field? methods" do
-      SpecNamespace::My_union.new.some_enum?.should be_false
-      SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).some_enum?.should be_true
-      SpecNamespace::My_union.new(:im_true => false).im_true?.should be_true
-      SpecNamespace::My_union.new(:im_true => true).im_true?.should be_true
+      expect(SpecNamespace::My_union.new.some_enum?).to be_falsey
+      expect(SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).some_enum?).to be_truthy
+      expect(SpecNamespace::My_union.new(:im_true => false).im_true?).to be_truthy
+      expect(SpecNamespace::My_union.new(:im_true => true).im_true?).to be_truthy
     end
 
     it "should pretty print binary fields" do
-      SpecNamespace::TestUnion.new(:binary_field => "\001\002\003").inspect.should == "<SpecNamespace::TestUnion binary_field: 010203>"
+      expect(SpecNamespace::TestUnion.new(:binary_field => "\001\002\003").inspect).to eq("<SpecNamespace::TestUnion binary_field: 010203>")
     end
 
     it "should be comparable" do
@@ -207,7 +207,7 @@
       for y in 0..3
         for x in 0..3
           # puts "#{objs[y].inspect} <=> #{objs[x].inspect} should == #{relationships[y][x]}"
-          (objs[y] <=> objs[x]).should == relationships[y][x]
+          expect(objs[y] <=> objs[x]).to eq(relationships[y][x])
         end
       end
     end
diff --git a/lib/rb/spec/unix_socket_spec.rb b/lib/rb/spec/unix_socket_spec.rb
index cb6cff3..8623e95 100644
--- a/lib/rb/spec/unix_socket_spec.rb
+++ b/lib/rb/spec/unix_socket_spec.rb
@@ -26,21 +26,26 @@
     before(:each) do
       @path = '/tmp/thrift_spec_socket'
       @socket = Thrift::UNIXSocket.new(@path)
-      @handle = mock("Handle", :closed? => false)
-      @handle.stub!(:close)
-      ::UNIXSocket.stub!(:new).and_return(@handle)
+      @handle = double("Handle", :closed? => false)
+      allow(@handle).to receive(:close)
+      allow(::UNIXSocket).to receive(:new).and_return(@handle)
     end
 
     it_should_behave_like "a socket"
 
     it "should raise a TransportException when it cannot open a socket" do
-      ::UNIXSocket.should_receive(:new).and_raise(StandardError)
-      lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
+      expect(::UNIXSocket).to receive(:new).and_raise(StandardError)
+      expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
     end
 
     it "should accept an optional timeout" do
-      ::UNIXSocket.stub!(:new)
-      Thrift::UNIXSocket.new(@path, 5).timeout.should == 5
+      allow(::UNIXSocket).to receive(:new)
+      expect(Thrift::UNIXSocket.new(@path, 5).timeout).to eq(5)
+    end
+    
+    it "should provide a reasonable to_s" do
+      allow(::UNIXSocket).to receive(:new)
+      expect(Thrift::UNIXSocket.new(@path).to_s).to eq("domain(#{@path})")
     end
   end
 
@@ -51,57 +56,61 @@
     end
 
     it "should create a handle when calling listen" do
-      UNIXServer.should_receive(:new).with(@path)
+      expect(UNIXServer).to receive(:new).with(@path)
       @socket.listen
     end
 
     it "should create a Thrift::UNIXSocket to wrap accepted sockets" do
-      handle = mock("UNIXServer")
-      UNIXServer.should_receive(:new).with(@path).and_return(handle)
+      handle = double("UNIXServer")
+      expect(UNIXServer).to receive(:new).with(@path).and_return(handle)
       @socket.listen
-      sock = mock("sock")
-      handle.should_receive(:accept).and_return(sock)
-      trans = mock("UNIXSocket")
-      Thrift::UNIXSocket.should_receive(:new).and_return(trans)
-      trans.should_receive(:handle=).with(sock)
-      @socket.accept.should == trans
+      sock = double("sock")
+      expect(handle).to receive(:accept).and_return(sock)
+      trans = double("UNIXSocket")
+      expect(Thrift::UNIXSocket).to receive(:new).and_return(trans)
+      expect(trans).to receive(:handle=).with(sock)
+      expect(@socket.accept).to eq(trans)
     end
 
     it "should close the handle when closed" do
-      handle = mock("UNIXServer", :closed? => false)
-      UNIXServer.should_receive(:new).with(@path).and_return(handle)
+      handle = double("UNIXServer", :closed? => false)
+      expect(UNIXServer).to receive(:new).with(@path).and_return(handle)
       @socket.listen
-      handle.should_receive(:close)
-      File.stub!(:delete)
+      expect(handle).to receive(:close)
+      allow(File).to receive(:delete)
       @socket.close
     end
 
     it "should delete the socket when closed" do
-      handle = mock("UNIXServer", :closed? => false)
-      UNIXServer.should_receive(:new).with(@path).and_return(handle)
+      handle = double("UNIXServer", :closed? => false)
+      expect(UNIXServer).to receive(:new).with(@path).and_return(handle)
       @socket.listen
-      handle.stub!(:close)
-      File.should_receive(:delete).with(@path)
+      allow(handle).to receive(:close)
+      expect(File).to receive(:delete).with(@path)
       @socket.close
     end
 
     it "should return nil when accepting if there is no handle" do
-      @socket.accept.should be_nil
+      expect(@socket.accept).to be_nil
     end
 
     it "should return true for closed? when appropriate" do
-      handle = mock("UNIXServer", :closed? => false)
-      UNIXServer.stub!(:new).and_return(handle)
-      File.stub!(:delete)
+      handle = double("UNIXServer", :closed? => false)
+      allow(UNIXServer).to receive(:new).and_return(handle)
+      allow(File).to receive(:delete)
       @socket.listen
-      @socket.should_not be_closed
-      handle.stub!(:close)
+      expect(@socket).not_to be_closed
+      allow(handle).to receive(:close)
       @socket.close
-      @socket.should be_closed
+      expect(@socket).to be_closed
       @socket.listen
-      @socket.should_not be_closed
-      handle.stub!(:closed?).and_return(true)
-      @socket.should be_closed
+      expect(@socket).not_to be_closed
+      allow(handle).to receive(:closed?).and_return(true)
+      expect(@socket).to be_closed
+    end
+
+    it "should provide a reasonable to_s" do
+      expect(@socket.to_s).to eq("domain(#{@path})")
     end
   end
 end
diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec
index 291b81f..e53194e 100644
--- a/lib/rb/thrift.gemspec
+++ b/lib/rb/thrift.gemspec
@@ -3,14 +3,14 @@
 
 Gem::Specification.new do |s|
   s.name        = 'thrift'
-  s.version     = '0.11.0.0'
-  s.authors     = ['Thrift Developers']
+  s.version     = '1.0.0'
+  s.authors     = ['Apache Thrift Developers']
   s.email       = ['dev@thrift.apache.org']
   s.homepage    = 'http://thrift.apache.org'
   s.summary     = %q{Ruby bindings for Apache Thrift}
   s.description = %q{Ruby bindings for the Apache Thrift RPC system}
-  s.license = 'Apache 2.0'
-  s.extensions = ['ext/extconf.rb']
+  s.license     = 'Apache-2.0'
+  s.extensions  = ['ext/extconf.rb']
 
   s.has_rdoc      = true
   s.rdoc_options  = %w[--line-numbers --inline-source --title Thrift --main README]
@@ -27,11 +27,14 @@
 
   s.require_paths = %w[lib ext]
 
-  s.add_development_dependency 'rspec', ['>= 2.10.0', '< 2.14.0']
-  s.add_development_dependency "rack", "~> 1.5"
-  s.add_development_dependency "rack-test", "~> 0.6"
-  s.add_development_dependency "thin", "~> 1.5"
-  s.add_development_dependency "bundler", "~> 1"
-  s.add_development_dependency 'rake', '~> 10.5'
+  s.add_development_dependency 'bundler',            '~> 1.11'
+  s.add_development_dependency 'pry',                '~> 0.11.3'
+  s.add_development_dependency 'pry-byebug',         '~> 3.6'
+  s.add_development_dependency 'pry-stack_explorer', '~> 0.4.9.2'
+  s.add_development_dependency 'rack',               '~> 2.0'
+  s.add_development_dependency 'rack-test',          '~> 0.8.3'
+  s.add_development_dependency 'rake',               '~> 12.3'
+  s.add_development_dependency 'rspec',              '~> 3.7'
+  s.add_development_dependency 'thin',               '~> 1.7'
 end
 
diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml
index 8e68175..ed32179 100644
--- a/lib/rs/Cargo.toml
+++ b/lib/rs/Cargo.toml
@@ -1,17 +1,17 @@
 [package]
 name = "thrift"
 description = "Rust bindings for the Apache Thrift RPC system"
-version = "0.11.0"
+version = "1.0.0"
 license = "Apache-2.0"
 authors = ["Apache Thrift Developers <dev@thrift.apache.org>"]
 homepage = "http://thrift.apache.org"
 documentation = "https://thrift.apache.org"
 readme = "README.md"
-exclude = ["Makefile*", "test/**"]
+exclude = ["Makefile*", "test/**", "*.iml"]
 keywords = ["thrift"]
 
 [dependencies]
-byteorder = "~1.1.0"
+byteorder = "~1.2.1"
 integer-encoding = "~1.0.4"
 log = "~0.3.8"
 threadpool = "~1.7.1"
diff --git a/lib/rs/README.md b/lib/rs/README.md
index 8b35eda..7c37a10 100644
--- a/lib/rs/README.md
+++ b/lib/rs/README.md
@@ -37,6 +37,57 @@
 
 Full [Rustdoc](https://docs.rs/thrift/)
 
+## Compatibility
+
+The Rust library and auto-generated code targets Rust versions 1.28+.
+It does not currently use any Rust 2018 features.
+
+### Breaking Changes
+
+Breaking changes are minimized. When they are made they will be outlined below with transition guidelines.
+
+##### Thrift 0.12.0
+
+* **[THRIFT-4529]** - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions
+
+    Previously, enum variants were uppercased in the auto-generated code.
+    For example, the following thrift enum:
+
+    ```thrift
+    // THRIFT
+    enum Operation {
+      ADD,
+      SUBTRACT,
+      MULTIPLY,
+      DIVIDE,
+    }
+    ```
+    
+    used to generate:
+    
+    ```rust
+    // OLD AUTO-GENERATED RUST
+    pub enum Operation {
+       ADD,
+       SUBTRACT,
+       MULTIPLY,
+       DIVIDE,
+     }
+    ```
+    It *now* generates:
+    ```rust
+    // NEW AUTO-GENERATED RUST
+    pub enum Operation {
+       Add,
+       Subtract,
+       Multiply,
+       Divide,
+     }
+    ```
+    
+    You will have to change all enum variants in your code to use camel-cased names.
+    This should be a search and replace.
+
 ## Contributing
 
 Bug reports and PRs are always welcome! Please see the
diff --git a/lib/rs/RELEASING.md b/lib/rs/RELEASING.md
new file mode 100644
index 0000000..073d7a0
--- /dev/null
+++ b/lib/rs/RELEASING.md
@@ -0,0 +1,57 @@
+# Publishing the thrift crate
+
+Publishing the Rust thrift crate is straightforward, and involves two major steps:
+
+1. Setting up your [crates.io](https://www.crates.io) account _(one-time)_
+
+2. Packaging/publishing the Rust thrift crate itself
+
+## Set up your crates.io account (one-time)
+
+1. Go to [crates.io](https://www.crates.io) and click the `Log In` button at the top right.
+
+   Log in **as the Github user with write permissions to the thrift repo!**
+
+2. Click your user icon button at the top right and select `Account Settings`.
+
+3. Click `New Token` next to `API Access`.
+
+   This generates a new API key that cargo uses to publish packages to crates.io.
+   Store this API key somewhere safe. If you will only use this Github account to
+   publish crates to crates.io you can follow the instructions to save the
+   generated key to `~/.cargo/credentials`.
+
+## Package and Publish
+
+You can use the automated script or run the release steps manually.
+
+**Important**: `cargo` expects that version numbers follow the semantic versioning format.
+This means that `THRIFT_RELEASE_VERSION` must have a major, minor and patch number, i.e., must
+be in the form `#.##.##`.
+
+#### Automated
+
+Run `./release.sh [THRIFT_RELEASE_VERSION]`.
+
+_Requires you to have stored your credentials in `~/.cargo/credentials`._
+
+#### Manual
+
+1. Edit `Cargo.toml` and update the `version = 1.0` key to `version = [THRIFT_RELEASE_VERSION]`
+
+2. `git add Cargo.toml`
+
+3. `git commit -m "Update thrift crate version to [THRIFT_RELEASE_VERSION]" -m "Client: rs"`
+
+4. `cargo login`
+
+    _(not required if you have stored your credentials in `~/.cargo/credentials`)_
+
+5. `cargo clean`
+
+6. `cargo package`
+
+   This step fails if there are any uncommitted or ignored files. Do **not** use the `--allow-dirty`
+   flag! Instead, add the highlighted files as entries in the `Cargo.toml` `exclude` key.
+
+7. `cargo publish`
diff --git a/lib/rs/release.sh b/lib/rs/release.sh
new file mode 100755
index 0000000..c4e5b48
--- /dev/null
+++ b/lib/rs/release.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+if ! [[ $# -eq 1 && $1 =~ ^[0-9](\.[0-9][0-9]*){2}$ ]]; then
+    (>&2 echo "Usage: ./publish-crate.sh [THRIFT_RELEASE_VERSION] ")
+    (>&2 echo "       THRIFT_RELEASE_VERSION is in semantic versioning format, i.e. #.##.##")
+    exit 1
+fi
+
+THRIFT_RELEASE_VERSION=${1:-}
+
+echo "Updating Cargo.toml to ${THRIFT_RELEASE_VERSION}"
+sed -i.old -e "s/^version = .*$/version = \"${THRIFT_RELEASE_VERSION}\"/g" Cargo.toml
+rm Cargo.toml.old
+
+echo "Committing updated Cargo.toml"
+git add Cargo.toml
+git commit -m "Update thrift crate version to ${THRIFT_RELEASE_VERSION}" -m "Client: rs"
+
+echo "Packaging and releasing rust thrift crate with version ${THRIFT_RELEASE_VERSION}"
+cargo clean
+cargo package
+cargo publish
diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs
index cc0ac78..16a2576 100644
--- a/lib/rs/src/errors.rs
+++ b/lib/rs/src/errors.rs
@@ -198,8 +198,9 @@
     /// Create an `ApplicationError` from its wire representation.
     ///
     /// Application code **should never** call this method directly.
-    pub fn read_application_error_from_in_protocol(i: &mut TInputProtocol,)
-        -> ::Result<ApplicationError> {
+    pub fn read_application_error_from_in_protocol(
+        i: &mut TInputProtocol,
+    ) -> ::Result<ApplicationError> {
         let mut message = "general remote error".to_owned();
         let mut kind = ApplicationErrorKind::Unknown;
 
@@ -224,9 +225,8 @@
                 }
                 2 => {
                     let remote_type_as_int = i.read_i32()?;
-                    let remote_kind: ApplicationErrorKind =
-                        TryFrom::try_from(remote_type_as_int)
-                            .unwrap_or(ApplicationErrorKind::Unknown);
+                    let remote_kind: ApplicationErrorKind = TryFrom::try_from(remote_type_as_int)
+                        .unwrap_or(ApplicationErrorKind::Unknown);
                     i.read_field_end()?;
                     kind = remote_kind;
                 }
@@ -238,12 +238,10 @@
 
         i.read_struct_end()?;
 
-        Ok(
-            ApplicationError {
-                kind: kind,
-                message: message,
-            },
-        )
+        Ok(ApplicationError {
+            kind: kind,
+            message: message,
+        })
     }
 
     /// Convert an `ApplicationError` into its wire representation and write
@@ -254,7 +252,9 @@
         e: &ApplicationError,
         o: &mut TOutputProtocol,
     ) -> ::Result<()> {
-        o.write_struct_begin(&TStructIdentifier { name: "TApplicationException".to_owned() },)?;
+        o.write_struct_begin(&TStructIdentifier {
+            name: "TApplicationException".to_owned(),
+        })?;
 
         let message_field = TFieldIdentifier::new("message", TType::String, 1);
         let type_field = TFieldIdentifier::new("type", TType::I32, 2);
@@ -309,23 +309,19 @@
 
 impl From<String> for Error {
     fn from(s: String) -> Self {
-        Error::Application(
-            ApplicationError {
-                kind: ApplicationErrorKind::Unknown,
-                message: s,
-            },
-        )
+        Error::Application(ApplicationError {
+            kind: ApplicationErrorKind::Unknown,
+            message: s,
+        })
     }
 }
 
 impl<'a> From<&'a str> for Error {
     fn from(s: &'a str) -> Self {
-        Error::Application(
-            ApplicationError {
-                kind: ApplicationErrorKind::Unknown,
-                message: String::from(s),
-            },
-        )
+        Error::Application(ApplicationError {
+            kind: ApplicationErrorKind::Unknown,
+            message: String::from(s),
+        })
     }
 }
 
@@ -427,16 +423,10 @@
             4 => Ok(TransportErrorKind::EndOfFile),
             5 => Ok(TransportErrorKind::NegativeSize),
             6 => Ok(TransportErrorKind::SizeLimit),
-            _ => {
-                Err(
-                    Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::Unknown,
-                            message: format!("cannot convert {} to TransportErrorKind", from),
-                        },
-                    ),
-                )
-            }
+            _ => Err(Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::Unknown,
+                message: format!("cannot convert {} to TransportErrorKind", from),
+            })),
         }
     }
 }
@@ -444,47 +434,29 @@
 impl From<io::Error> for Error {
     fn from(err: io::Error) -> Self {
         match err.kind() {
-            io::ErrorKind::ConnectionReset |
-            io::ErrorKind::ConnectionRefused |
-            io::ErrorKind::NotConnected => {
-                Error::Transport(
-                    TransportError {
-                        kind: TransportErrorKind::NotOpen,
-                        message: err.description().to_owned(),
-                    },
-                )
-            }
-            io::ErrorKind::AlreadyExists => {
-                Error::Transport(
-                    TransportError {
-                        kind: TransportErrorKind::AlreadyOpen,
-                        message: err.description().to_owned(),
-                    },
-                )
-            }
-            io::ErrorKind::TimedOut => {
-                Error::Transport(
-                    TransportError {
-                        kind: TransportErrorKind::TimedOut,
-                        message: err.description().to_owned(),
-                    },
-                )
-            }
-            io::ErrorKind::UnexpectedEof => {
-                Error::Transport(
-                    TransportError {
-                        kind: TransportErrorKind::EndOfFile,
-                        message: err.description().to_owned(),
-                    },
-                )
-            }
+            io::ErrorKind::ConnectionReset
+            | io::ErrorKind::ConnectionRefused
+            | io::ErrorKind::NotConnected => Error::Transport(TransportError {
+                kind: TransportErrorKind::NotOpen,
+                message: err.description().to_owned(),
+            }),
+            io::ErrorKind::AlreadyExists => Error::Transport(TransportError {
+                kind: TransportErrorKind::AlreadyOpen,
+                message: err.description().to_owned(),
+            }),
+            io::ErrorKind::TimedOut => Error::Transport(TransportError {
+                kind: TransportErrorKind::TimedOut,
+                message: err.description().to_owned(),
+            }),
+            io::ErrorKind::UnexpectedEof => Error::Transport(TransportError {
+                kind: TransportErrorKind::EndOfFile,
+                message: err.description().to_owned(),
+            }),
             _ => {
-                Error::Transport(
-                    TransportError {
-                        kind: TransportErrorKind::Unknown,
-                        message: err.description().to_owned(), // FIXME: use io error's debug string
-                    },
-                )
+                Error::Transport(TransportError {
+                    kind: TransportErrorKind::Unknown,
+                    message: err.description().to_owned(), // FIXME: use io error's debug string
+                })
             }
         }
     }
@@ -492,12 +464,10 @@
 
 impl From<string::FromUtf8Error> for Error {
     fn from(err: string::FromUtf8Error) -> Self {
-        Error::Protocol(
-            ProtocolError {
-                kind: ProtocolErrorKind::InvalidData,
-                message: err.description().to_owned(), // FIXME: use fmt::Error's debug string
-            },
-        )
+        Error::Protocol(ProtocolError {
+            kind: ProtocolErrorKind::InvalidData,
+            message: err.description().to_owned(), // FIXME: use fmt::Error's debug string
+        })
     }
 }
 
@@ -583,16 +553,10 @@
             4 => Ok(ProtocolErrorKind::BadVersion),
             5 => Ok(ProtocolErrorKind::NotImplemented),
             6 => Ok(ProtocolErrorKind::DepthLimit),
-            _ => {
-                Err(
-                    Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::Unknown,
-                            message: format!("cannot convert {} to ProtocolErrorKind", from),
-                        },
-                    ),
-                )
-            }
+            _ => Err(Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::Unknown,
+                message: format!("cannot convert {} to ProtocolErrorKind", from),
+            })),
         }
     }
 }
@@ -697,16 +661,10 @@
             8 => Ok(ApplicationErrorKind::InvalidTransform),
             9 => Ok(ApplicationErrorKind::InvalidProtocol),
             10 => Ok(ApplicationErrorKind::UnsupportedClientType),
-            _ => {
-                Err(
-                    Error::Application(
-                        ApplicationError {
-                            kind: ApplicationErrorKind::Unknown,
-                            message: format!("cannot convert {} to ApplicationErrorKind", from),
-                        },
-                    ),
-                )
-            }
+            _ => Err(Error::Application(ApplicationError {
+                kind: ApplicationErrorKind::Unknown,
+                message: format!("cannot convert {} to ApplicationErrorKind", from),
+            })),
         }
     }
 }
diff --git a/lib/rs/src/lib.rs b/lib/rs/src/lib.rs
index 7ebb10c..ca5c7d6 100644
--- a/lib/rs/src/lib.rs
+++ b/lib/rs/src/lib.rs
@@ -63,13 +63,11 @@
 /// return the value contained in the result, i.e. `expr.unwrap()`.
 #[cfg(test)]
 macro_rules! assert_success {
-    ($e: expr) => {
-        {
-            let res = $e;
-            assert!(res.is_ok());
-            res.unwrap()
-        }
-    }
+    ($e: expr) => {{
+        let res = $e;
+        assert!(res.is_ok());
+        res.unwrap()
+    }};
 }
 
 pub mod protocol;
diff --git a/lib/rs/src/protocol/binary.rs b/lib/rs/src/protocol/binary.rs
index 1710733..19aff3d 100644
--- a/lib/rs/src/protocol/binary.rs
+++ b/lib/rs/src/protocol/binary.rs
@@ -19,11 +19,13 @@
 use std::convert::From;
 use try_from::TryFrom;
 
-use {ProtocolError, ProtocolErrorKind};
-use transport::{TReadTransport, TWriteTransport};
-use super::{TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier,
-            TMapIdentifier, TMessageIdentifier, TMessageType};
+use super::{
+    TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
+    TMessageIdentifier, TMessageType,
+};
 use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
+use transport::{TReadTransport, TWriteTransport};
+use {ProtocolError, ProtocolErrorKind};
 
 const BINARY_PROTOCOL_VERSION_1: u32 = 0x80010000;
 
@@ -90,14 +92,10 @@
             // apparently we got a protocol-version header - check
             // it, and if it matches, read the rest of the fields
             if first_bytes[0..2] != [0x80, 0x01] {
-                Err(
-                    ::Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::BadVersion,
-                            message: format!("received bad version: {:?}", &first_bytes[0..2]),
-                        },
-                    ),
-                )
+                Err(::Error::Protocol(ProtocolError {
+                    kind: ProtocolErrorKind::BadVersion,
+                    message: format!("received bad version: {:?}", &first_bytes[0..2]),
+                }))
             } else {
                 let message_type: TMessageType = TryFrom::try_from(first_bytes[3])?;
                 let name = self.read_string()?;
@@ -110,20 +108,16 @@
             if self.strict {
                 // we're in strict mode however, and that always
                 // requires the protocol-version header to be written first
-                Err(
-                    ::Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::BadVersion,
-                            message: format!("received bad version: {:?}", &first_bytes[0..2]),
-                        },
-                    ),
-                )
+                Err(::Error::Protocol(ProtocolError {
+                    kind: ProtocolErrorKind::BadVersion,
+                    message: format!("received bad version: {:?}", &first_bytes[0..2]),
+                }))
             } else {
                 // in the non-strict version the first message field
                 // is the message name. strings (byte arrays) are length-prefixed,
                 // so we've just read the length in the first 4 bytes
                 let name_size = BigEndian::read_i32(&first_bytes) as usize;
-                let mut name_buf: Vec<u8> = Vec::with_capacity(name_size);
+                let mut name_buf: Vec<u8> = vec![0; name_size];
                 self.transport.read_exact(&mut name_buf)?;
                 let name = String::from_utf8(name_buf)?;
 
@@ -154,7 +148,9 @@
             TType::Stop => Ok(0),
             _ => self.read_i16(),
         }?;
-        Ok(TFieldIdentifier::new::<Option<String>, String, i16>(None, field_type, id),)
+        Ok(TFieldIdentifier::new::<Option<String>, String, i16>(
+            None, field_type, id,
+        ))
     }
 
     fn read_field_end(&mut self) -> ::Result<()> {
@@ -183,27 +179,19 @@
     }
 
     fn read_i16(&mut self) -> ::Result<i16> {
-        self.transport
-            .read_i16::<BigEndian>()
-            .map_err(From::from)
+        self.transport.read_i16::<BigEndian>().map_err(From::from)
     }
 
     fn read_i32(&mut self) -> ::Result<i32> {
-        self.transport
-            .read_i32::<BigEndian>()
-            .map_err(From::from)
+        self.transport.read_i32::<BigEndian>().map_err(From::from)
     }
 
     fn read_i64(&mut self) -> ::Result<i64> {
-        self.transport
-            .read_i64::<BigEndian>()
-            .map_err(From::from)
+        self.transport.read_i64::<BigEndian>().map_err(From::from)
     }
 
     fn read_double(&mut self) -> ::Result<f64> {
-        self.transport
-            .read_f64::<BigEndian>()
-            .map_err(From::from)
+        self.transport.read_f64::<BigEndian>().map_err(From::from)
     }
 
     fn read_string(&mut self) -> ::Result<String> {
@@ -312,13 +300,6 @@
             transport: transport,
         }
     }
-
-    fn write_transport(&mut self, buf: &[u8]) -> ::Result<()> {
-        self.transport
-            .write(buf)
-            .map(|_| ())
-            .map_err(From::from)
-    }
 }
 
 impl<T> TOutputProtocol for TBinaryOutputProtocol<T>
@@ -353,17 +334,13 @@
 
     fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> {
         if identifier.id.is_none() && identifier.field_type != TType::Stop {
-            return Err(
-                ::Error::Protocol(
-                    ProtocolError {
-                        kind: ProtocolErrorKind::Unknown,
-                        message: format!(
-                            "cannot write identifier {:?} without sequence number",
-                            &identifier
-                        ),
-                    },
+            return Err(::Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::Unknown,
+                message: format!(
+                    "cannot write identifier {:?} without sequence number",
+                    &identifier
                 ),
-            );
+            }));
         }
 
         self.write_byte(field_type_to_u8(identifier.field_type))?;
@@ -384,7 +361,7 @@
 
     fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> {
         self.write_i32(b.len() as i32)?;
-        self.write_transport(b)
+        self.transport.write_all(b).map_err(From::from)
     }
 
     fn write_bool(&mut self, b: bool) -> ::Result<()> {
@@ -400,27 +377,19 @@
     }
 
     fn write_i16(&mut self, i: i16) -> ::Result<()> {
-        self.transport
-            .write_i16::<BigEndian>(i)
-            .map_err(From::from)
+        self.transport.write_i16::<BigEndian>(i).map_err(From::from)
     }
 
     fn write_i32(&mut self, i: i32) -> ::Result<()> {
-        self.transport
-            .write_i32::<BigEndian>(i)
-            .map_err(From::from)
+        self.transport.write_i32::<BigEndian>(i).map_err(From::from)
     }
 
     fn write_i64(&mut self, i: i64) -> ::Result<()> {
-        self.transport
-            .write_i64::<BigEndian>(i)
-            .map_err(From::from)
+        self.transport.write_i64::<BigEndian>(i).map_err(From::from)
     }
 
     fn write_double(&mut self, d: f64) -> ::Result<()> {
-        self.transport
-            .write_f64::<BigEndian>(d)
-            .map_err(From::from)
+        self.transport.write_f64::<BigEndian>(d).map_err(From::from)
     }
 
     fn write_string(&mut self, s: &str) -> ::Result<()> {
@@ -527,36 +496,32 @@
         0x0F => Ok(TType::List),
         0x10 => Ok(TType::Utf8),
         0x11 => Ok(TType::Utf16),
-        unkn => {
-            Err(
-                ::Error::Protocol(
-                    ProtocolError {
-                        kind: ProtocolErrorKind::InvalidData,
-                        message: format!("cannot convert {} to TType", unkn),
-                    },
-                ),
-            )
-        }
+        unkn => Err(::Error::Protocol(ProtocolError {
+            kind: ProtocolErrorKind::InvalidData,
+            message: format!("cannot convert {} to TType", unkn),
+        })),
     }
 }
 
 #[cfg(test)]
 mod tests {
 
-    use protocol::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier,
-                   TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier,
-                   TStructIdentifier, TType};
+    use protocol::{
+        TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
+        TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
+    };
     use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
 
     use super::*;
 
     #[test]
-    fn must_write_message_call_begin() {
-        let (_, mut o_prot) = test_objects();
+    fn must_write_strict_message_call_begin() {
+        let (_, mut o_prot) = test_objects(true);
 
         let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 16] = [
             0x80,
             0x01,
@@ -580,12 +545,40 @@
     }
 
     #[test]
-    fn must_write_message_reply_begin() {
-        let (_, mut o_prot) = test_objects();
+    fn must_write_non_strict_message_call_begin() {
+        let (_, mut o_prot) = test_objects(false);
+
+        let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
+        assert!(o_prot.write_message_begin(&ident).is_ok());
+
+        #[cfg_attr(rustfmt, rustfmt::skip)]
+        let expected: [u8; 13] = [
+            0x00,
+            0x00,
+            0x00,
+            0x04,
+            0x74,
+            0x65,
+            0x73,
+            0x74,
+            0x01,
+            0x00,
+            0x00,
+            0x00,
+            0x01,
+        ];
+
+        assert_eq_written_bytes!(o_prot, expected);
+    }
+
+    #[test]
+    fn must_write_strict_message_reply_begin() {
+        let (_, mut o_prot) = test_objects(true);
 
         let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 16] = [
             0x80,
             0x01,
@@ -609,8 +602,48 @@
     }
 
     #[test]
+    fn must_write_non_strict_message_reply_begin() {
+        let (_, mut o_prot) = test_objects(false);
+
+        let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
+        assert!(o_prot.write_message_begin(&ident).is_ok());
+
+        #[cfg_attr(rustfmt, rustfmt::skip)]
+        let expected: [u8; 13] = [
+            0x00,
+            0x00,
+            0x00,
+            0x04,
+            0x74,
+            0x65,
+            0x73,
+            0x74,
+            0x02,
+            0x00,
+            0x00,
+            0x00,
+            0x0A,
+        ];
+
+        assert_eq_written_bytes!(o_prot, expected);
+    }
+
+    #[test]
     fn must_round_trip_strict_message_begin() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
+
+        let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
+        assert!(o_prot.write_message_begin(&sent_ident).is_ok());
+
+        copy_write_buffer_to_read_buffer!(o_prot);
+
+        let received_ident = assert_success!(i_prot.read_message_begin());
+        assert_eq!(&received_ident, &sent_ident);
+    }
+
+    #[test]
+    fn must_round_trip_non_strict_message_begin() {
+        let (mut i_prot, mut o_prot) = test_objects(false);
 
         let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
         assert!(o_prot.write_message_begin(&sent_ident).is_ok());
@@ -623,28 +656,29 @@
 
     #[test]
     fn must_write_message_end() {
-        assert_no_write(|o| o.write_message_end());
+        assert_no_write(|o| o.write_message_end(), true);
     }
 
     #[test]
     fn must_write_struct_begin() {
-        assert_no_write(|o| o.write_struct_begin(&TStructIdentifier::new("foo")));
+        assert_no_write(
+            |o| o.write_struct_begin(&TStructIdentifier::new("foo")),
+            true,
+        );
     }
 
     #[test]
     fn must_write_struct_end() {
-        assert_no_write(|o| o.write_struct_end());
+        assert_no_write(|o| o.write_struct_end(), true);
     }
 
     #[test]
     fn must_write_field_begin() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
-        assert!(
-            o_prot
-                .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
-                .is_ok()
-        );
+        assert!(o_prot
+            .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22))
+            .is_ok());
 
         let expected: [u8; 3] = [0x0B, 0x00, 0x16];
         assert_eq_written_bytes!(o_prot, expected);
@@ -652,7 +686,7 @@
 
     #[test]
     fn must_round_trip_field_begin() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
         let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20);
         assert!(o_prot.write_field_begin(&sent_field_ident).is_ok());
@@ -670,7 +704,7 @@
 
     #[test]
     fn must_write_stop_field() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
         assert!(o_prot.write_field_stop().is_ok());
 
@@ -680,7 +714,7 @@
 
     #[test]
     fn must_round_trip_field_stop() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
         assert!(o_prot.write_field_stop().is_ok());
 
@@ -698,18 +732,16 @@
 
     #[test]
     fn must_write_field_end() {
-        assert_no_write(|o| o.write_field_end());
+        assert_no_write(|o| o.write_field_end(), true);
     }
 
     #[test]
     fn must_write_list_begin() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
-        assert!(
-            o_prot
-                .write_list_begin(&TListIdentifier::new(TType::Bool, 5))
-                .is_ok()
-        );
+        assert!(o_prot
+            .write_list_begin(&TListIdentifier::new(TType::Bool, 5))
+            .is_ok());
 
         let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05];
         assert_eq_written_bytes!(o_prot, expected);
@@ -717,7 +749,7 @@
 
     #[test]
     fn must_round_trip_list_begin() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
         let ident = TListIdentifier::new(TType::List, 900);
         assert!(o_prot.write_list_begin(&ident).is_ok());
@@ -730,18 +762,16 @@
 
     #[test]
     fn must_write_list_end() {
-        assert_no_write(|o| o.write_list_end());
+        assert_no_write(|o| o.write_list_end(), true);
     }
 
     #[test]
     fn must_write_set_begin() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
-        assert!(
-            o_prot
-                .write_set_begin(&TSetIdentifier::new(TType::I16, 7))
-                .is_ok()
-        );
+        assert!(o_prot
+            .write_set_begin(&TSetIdentifier::new(TType::I16, 7))
+            .is_ok());
 
         let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07];
         assert_eq_written_bytes!(o_prot, expected);
@@ -749,7 +779,7 @@
 
     #[test]
     fn must_round_trip_set_begin() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
         let ident = TSetIdentifier::new(TType::I64, 2000);
         assert!(o_prot.write_set_begin(&ident).is_ok());
@@ -763,18 +793,16 @@
 
     #[test]
     fn must_write_set_end() {
-        assert_no_write(|o| o.write_set_end());
+        assert_no_write(|o| o.write_set_end(), true);
     }
 
     #[test]
     fn must_write_map_begin() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
-        assert!(
-            o_prot
-                .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
-                .is_ok()
-        );
+        assert!(o_prot
+            .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32))
+            .is_ok());
 
         let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20];
         assert_eq_written_bytes!(o_prot, expected);
@@ -782,7 +810,7 @@
 
     #[test]
     fn must_round_trip_map_begin() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
         let ident = TMapIdentifier::new(TType::Map, TType::Set, 100);
         assert!(o_prot.write_map_begin(&ident).is_ok());
@@ -795,12 +823,12 @@
 
     #[test]
     fn must_write_map_end() {
-        assert_no_write(|o| o.write_map_end());
+        assert_no_write(|o| o.write_map_end(), true);
     }
 
     #[test]
     fn must_write_bool_true() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
         assert!(o_prot.write_bool(true).is_ok());
 
@@ -810,7 +838,7 @@
 
     #[test]
     fn must_write_bool_false() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
         assert!(o_prot.write_bool(false).is_ok());
 
@@ -820,7 +848,7 @@
 
     #[test]
     fn must_read_bool_true() {
-        let (mut i_prot, _) = test_objects();
+        let (mut i_prot, _) = test_objects(true);
 
         set_readable_bytes!(i_prot, &[0x01]);
 
@@ -830,7 +858,7 @@
 
     #[test]
     fn must_read_bool_false() {
-        let (mut i_prot, _) = test_objects();
+        let (mut i_prot, _) = test_objects(true);
 
         set_readable_bytes!(i_prot, &[0x00]);
 
@@ -840,7 +868,7 @@
 
     #[test]
     fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() {
-        let (mut i_prot, _) = test_objects();
+        let (mut i_prot, _) = test_objects(true);
 
         set_readable_bytes!(i_prot, &[0xAC]);
 
@@ -850,7 +878,7 @@
 
     #[test]
     fn must_write_bytes() {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(true);
 
         let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF];
 
@@ -863,8 +891,9 @@
 
     #[test]
     fn must_round_trip_bytes() {
-        let (mut i_prot, mut o_prot) = test_objects();
+        let (mut i_prot, mut o_prot) = test_objects(true);
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let bytes: [u8; 25] = [
             0x20,
             0xFD,
@@ -901,25 +930,27 @@
         assert_eq!(&received_bytes, &bytes);
     }
 
-    fn test_objects()
-        -> (TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
-            TBinaryOutputProtocol<WriteHalf<TBufferChannel>>)
-    {
+    fn test_objects(
+        strict: bool,
+    ) -> (
+        TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
+        TBinaryOutputProtocol<WriteHalf<TBufferChannel>>,
+    ) {
         let mem = TBufferChannel::with_capacity(40, 40);
 
         let (r_mem, w_mem) = mem.split().unwrap();
 
-        let i_prot = TBinaryInputProtocol::new(r_mem, true);
-        let o_prot = TBinaryOutputProtocol::new(w_mem, true);
+        let i_prot = TBinaryInputProtocol::new(r_mem, strict);
+        let o_prot = TBinaryOutputProtocol::new(w_mem, strict);
 
         (i_prot, o_prot)
     }
 
-    fn assert_no_write<F>(mut write_fn: F)
+    fn assert_no_write<F>(mut write_fn: F, strict: bool)
     where
         F: FnMut(&mut TBinaryOutputProtocol<WriteHalf<TBufferChannel>>) -> ::Result<()>,
     {
-        let (_, mut o_prot) = test_objects();
+        let (_, mut o_prot) = test_objects(strict);
         assert!(write_fn(&mut o_prot).is_ok());
         assert_eq!(o_prot.transport.write_bytes().len(), 0);
     }
diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs
index dfe11f8..df5edaa 100644
--- a/lib/rs/src/protocol/compact.rs
+++ b/lib/rs/src/protocol/compact.rs
@@ -18,12 +18,15 @@
 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
 use integer_encoding::{VarIntReader, VarIntWriter};
 use std::convert::From;
+use std::io;
 use try_from::TryFrom;
 
-use transport::{TReadTransport, TWriteTransport};
-use super::{TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier,
-            TMapIdentifier, TMessageIdentifier, TMessageType};
+use super::{
+    TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier,
+    TMessageIdentifier, TMessageType,
+};
 use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType};
+use transport::{TReadTransport, TWriteTransport};
 
 const COMPACT_PROTOCOL_ID: u8 = 0x82;
 const COMPACT_VERSION: u8 = 0x01;
@@ -102,14 +105,10 @@
     fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
         let compact_id = self.read_byte()?;
         if compact_id != COMPACT_PROTOCOL_ID {
-            Err(
-                ::Error::Protocol(
-                    ::ProtocolError {
-                        kind: ::ProtocolErrorKind::BadVersion,
-                        message: format!("invalid compact protocol header {:?}", compact_id),
-                    },
-                ),
-            )
+            Err(::Error::Protocol(::ProtocolError {
+                kind: ::ProtocolErrorKind::BadVersion,
+                message: format!("invalid compact protocol header {:?}", compact_id),
+            }))
         } else {
             Ok(())
         }?;
@@ -117,17 +116,13 @@
         let type_and_byte = self.read_byte()?;
         let received_version = type_and_byte & COMPACT_VERSION_MASK;
         if received_version != COMPACT_VERSION {
-            Err(
-                ::Error::Protocol(
-                    ::ProtocolError {
-                        kind: ::ProtocolErrorKind::BadVersion,
-                        message: format!(
-                            "cannot process compact protocol version {:?}",
-                            received_version
-                        ),
-                    },
+            Err(::Error::Protocol(::ProtocolError {
+                kind: ::ProtocolErrorKind::BadVersion,
+                message: format!(
+                    "cannot process compact protocol version {:?}",
+                    received_version
                 ),
-            )
+            }))
         } else {
             Ok(())
         }?;
@@ -139,7 +134,11 @@
 
         self.last_read_field_id = 0;
 
-        Ok(TMessageIdentifier::new(service_call_name, message_type, sequence_number),)
+        Ok(TMessageIdentifier::new(
+            service_call_name,
+            message_type,
+            sequence_number,
+        ))
     }
 
     fn read_message_end(&mut self) -> ::Result<()> {
@@ -153,7 +152,8 @@
     }
 
     fn read_struct_end(&mut self) -> ::Result<()> {
-        self.last_read_field_id = self.read_field_id_stack
+        self.last_read_field_id = self
+            .read_field_id_stack
             .pop()
             .expect("should have previous field ids");
         Ok(())
@@ -178,15 +178,13 @@
         }?;
 
         match field_type {
-            TType::Stop => {
-                Ok(
-                    TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
-                        None,
-                        TType::Stop,
-                        None,
-                    ),
-                )
-            }
+            TType::Stop => Ok(
+                TFieldIdentifier::new::<Option<String>, String, Option<i16>>(
+                    None,
+                    TType::Stop,
+                    None,
+                ),
+            ),
             _ => {
                 if field_delta != 0 {
                     self.last_read_field_id += field_delta as i16;
@@ -194,13 +192,11 @@
                     self.last_read_field_id = self.read_i16()?;
                 };
 
-                Ok(
-                    TFieldIdentifier {
-                        name: None,
-                        field_type: field_type,
-                        id: Some(self.last_read_field_id),
-                    },
-                )
+                Ok(TFieldIdentifier {
+                    name: None,
+                    field_type: field_type,
+                    id: Some(self.last_read_field_id),
+                })
             }
         }
     }
@@ -217,16 +213,10 @@
                 match b {
                     0x01 => Ok(true),
                     0x02 => Ok(false),
-                    unkn => {
-                        Err(
-                            ::Error::Protocol(
-                                ::ProtocolError {
-                                    kind: ::ProtocolErrorKind::InvalidData,
-                                    message: format!("cannot convert {} into bool", unkn),
-                                },
-                            ),
-                        )
-                    }
+                    unkn => Err(::Error::Protocol(::ProtocolError {
+                        kind: ::ProtocolErrorKind::InvalidData,
+                        message: format!("cannot convert {} into bool", unkn),
+                    })),
                 }
             }
         }
@@ -258,9 +248,7 @@
     }
 
     fn read_double(&mut self) -> ::Result<f64> {
-        self.transport
-            .read_f64::<BigEndian>()
-            .map_err(From::from)
+        self.transport.read_f64::<BigEndian>().map_err(From::from)
     }
 
     fn read_string(&mut self) -> ::Result<String> {
@@ -314,6 +302,15 @@
     }
 }
 
+impl<T> io::Seek for TCompactInputProtocol<T>
+where
+    T: io::Seek + TReadTransport,
+{
+    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
+        self.transport.seek(pos)
+    }
+}
+
 /// Factory for creating instances of `TCompactInputProtocol`.
 #[derive(Default)]
 pub struct TCompactInputProtocolFactory;
@@ -439,7 +436,8 @@
 
     fn write_struct_end(&mut self) -> ::Result<()> {
         self.assert_no_pending_bool_write();
-        self.last_write_field_id = self.write_field_id_stack
+        self.last_write_field_id = self
+            .write_field_id_stack
             .pop()
             .expect("should have previous field ids");
         Ok(())
@@ -451,7 +449,7 @@
                 if self.pending_write_bool_field_identifier.is_some() {
                     panic!(
                         "should not have a pending bool while writing another bool with id: \
-                            {:?}",
+                         {:?}",
                         identifier
                     )
                 }
@@ -460,9 +458,7 @@
             }
             _ => {
                 let field_type = type_to_u8(identifier.field_type);
-                let field_id = identifier
-                    .id
-                    .expect("non-stop field should have field id");
+                let field_id = identifier.id.expect("non-stop field should have field id");
                 self.write_field_header(field_type, field_id)
             }
         }
@@ -526,9 +522,7 @@
     }
 
     fn write_double(&mut self, d: f64) -> ::Result<()> {
-        self.transport
-            .write_f64::<BigEndian>(d)
-            .map_err(From::from)
+        self.transport.write_f64::<BigEndian>(d).map_err(From::from)
     }
 
     fn write_string(&mut self, s: &str) -> ::Result<()> {
@@ -584,10 +578,7 @@
     //
 
     fn write_byte(&mut self, b: u8) -> ::Result<()> {
-        self.transport
-            .write(&[b])
-            .map_err(From::from)
-            .map(|_| ())
+        self.transport.write(&[b]).map_err(From::from).map(|_| ())
     }
 }
 
@@ -628,7 +619,10 @@
         TType::Set => 0x0A,
         TType::Map => 0x0B,
         TType::Struct => 0x0C,
-        _ => panic!(format!("should not have attempted to convert {} to u8", field_type)),
+        _ => panic!(format!(
+            "should not have attempted to convert {} to u8",
+            field_type
+        )),
     }
 }
 
@@ -652,25 +646,20 @@
         0x0A => Ok(TType::Set),
         0x0B => Ok(TType::Map),
         0x0C => Ok(TType::Struct),
-        unkn => {
-            Err(
-                ::Error::Protocol(
-                    ::ProtocolError {
-                        kind: ::ProtocolErrorKind::InvalidData,
-                        message: format!("cannot convert {} into TType", unkn),
-                    },
-                ),
-            )
-        }
+        unkn => Err(::Error::Protocol(::ProtocolError {
+            kind: ::ProtocolErrorKind::InvalidData,
+            message: format!("cannot convert {} into TType", unkn),
+        })),
     }
 }
 
 #[cfg(test)]
 mod tests {
 
-    use protocol::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier,
-                   TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier,
-                   TStructIdentifier, TType};
+    use protocol::{
+        TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
+        TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType,
+    };
     use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
 
     use super::*;
@@ -679,8 +668,13 @@
     fn must_write_message_begin_0() {
         let (_, mut o_prot) = test_objects();
 
-        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new("foo", TMessageType::Call, 431)));
+        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
+            "foo",
+            TMessageType::Call,
+            431
+        )));
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 8] = [
             0x82, /* protocol ID */
             0x21, /* message type | protocol version */
@@ -699,10 +693,13 @@
     fn must_write_message_begin_1() {
         let (_, mut o_prot) = test_objects();
 
-        assert_success!(
-            o_prot.write_message_begin(&TMessageIdentifier::new("bar", TMessageType::Reply, 991828))
-        );
+        assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
+            "bar",
+            TMessageType::Reply,
+            991828
+        )));
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 9] = [
             0x82, /* protocol ID */
             0x41, /* message type | protocol version */
@@ -766,6 +763,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 5] = [
             0x03, /* field type */
             0x00, /* first field id */
@@ -880,6 +878,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 4] = [
             0x15, /* field delta (1) | field type */
             0x1A, /* field delta (1) | field type */
@@ -992,6 +991,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 8] = [
             0x05, /* field type */
             0x00, /* first field id */
@@ -1115,6 +1115,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 10] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1279,6 +1280,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1451,6 +1453,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1623,6 +1626,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x08, /* field type */
@@ -1792,6 +1796,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 8] = [
             0x16, /* field delta (1) | field type */
             0x08, /* field type */
@@ -1957,6 +1962,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 7] = [
             0x11, /* field delta (1) | true */
             0x82, /* field delta (8) | false */
@@ -2147,8 +2153,7 @@
 
         let expected: [u8; 3] = [
             0xF9, /* 0xF0 | elem_type */
-            0x8F,
-            0x4E /* size as varint */,
+            0x8F, 0x4E, /* size as varint */
         ];
 
         assert_eq_written_bytes!(o_prot, expected);
@@ -2206,9 +2211,7 @@
 
         let expected: [u8; 4] = [
             0xF7, /* 0xF0 | elem_type */
-            0xD3,
-            0xBA,
-            0x01 /* size as varint */,
+            0xD3, 0xBA, 0x01, /* size as varint */
         ];
 
         assert_eq_written_bytes!(o_prot, expected);
@@ -2256,10 +2259,10 @@
         assert_eq!(
             &res,
             &TMapIdentifier {
-                 key_type: None,
-                 value_type: None,
-                 size: 0,
-             }
+                key_type: None,
+                value_type: None,
+                size: 0,
+            }
         );
     }
 
@@ -2267,12 +2270,15 @@
     fn must_write_map_begin() {
         let (_, mut o_prot) = test_objects();
 
-        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::String, 238)));
+        assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(
+            TType::Double,
+            TType::String,
+            238
+        )));
 
         let expected: [u8; 3] = [
-            0xEE,
-            0x01, /* size as varint */
-            0x78 /* key type | val type */,
+            0xEE, 0x01, /* size as varint */
+            0x78, /* key type | val type */
         ];
 
         assert_eq_written_bytes!(o_prot, expected);
@@ -2310,7 +2316,7 @@
             0x01, /* size as varint */
             0x11, /* key type | val type */
             0x01, /* key: true */
-            0x02 /* val: false */,
+            0x02, /* val: false */
         ];
 
         assert_eq_written_bytes!(o_prot, expected);
@@ -2355,10 +2361,10 @@
         assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer
     }
 
-    fn test_objects()
-        -> (TCompactInputProtocol<ReadHalf<TBufferChannel>>,
-            TCompactOutputProtocol<WriteHalf<TBufferChannel>>)
-    {
+    fn test_objects() -> (
+        TCompactInputProtocol<ReadHalf<TBufferChannel>>,
+        TCompactOutputProtocol<WriteHalf<TBufferChannel>>,
+    ) {
         let mem = TBufferChannel::with_capacity(80, 80);
 
         let (r_mem, w_mem) = mem.split().unwrap();
diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs
index 4f13914..11c0289 100644
--- a/lib/rs/src/protocol/mod.rs
+++ b/lib/rs/src/protocol/mod.rs
@@ -57,38 +57,34 @@
 //! protocol.write_field_end().unwrap();
 //! ```
 
+use std::convert::From;
 use std::fmt;
 use std::fmt::{Display, Formatter};
-use std::convert::From;
 use try_from::TryFrom;
 
-use {ProtocolError, ProtocolErrorKind};
 use transport::{TReadTransport, TWriteTransport};
+use {ProtocolError, ProtocolErrorKind};
 
 #[cfg(test)]
 macro_rules! assert_eq_written_bytes {
-    ($o_prot:ident, $expected_bytes:ident) => {
-        {
-            assert_eq!($o_prot.transport.write_bytes(), &$expected_bytes);
-        }
-    };
+    ($o_prot:ident, $expected_bytes:ident) => {{
+        assert_eq!($o_prot.transport.write_bytes(), &$expected_bytes);
+    }};
 }
 
 // FIXME: should take both read and write
 #[cfg(test)]
 macro_rules! copy_write_buffer_to_read_buffer {
-    ($o_prot:ident) => {
-        {
-            $o_prot.transport.copy_write_buffer_to_read_buffer();
-        }
-    };
+    ($o_prot:ident) => {{
+        $o_prot.transport.copy_write_buffer_to_read_buffer();
+    }};
 }
 
 #[cfg(test)]
 macro_rules! set_readable_bytes {
     ($i_prot:ident, $bytes:expr) => {
         $i_prot.transport.set_readable_bytes($bytes);
-    }
+    };
 }
 
 mod binary;
@@ -96,10 +92,14 @@
 mod multiplexed;
 mod stored;
 
-pub use self::binary::{TBinaryInputProtocol, TBinaryInputProtocolFactory, TBinaryOutputProtocol,
-                       TBinaryOutputProtocolFactory};
-pub use self::compact::{TCompactInputProtocol, TCompactInputProtocolFactory,
-                        TCompactOutputProtocol, TCompactOutputProtocolFactory};
+pub use self::binary::{
+    TBinaryInputProtocol, TBinaryInputProtocolFactory, TBinaryOutputProtocol,
+    TBinaryOutputProtocolFactory,
+};
+pub use self::compact::{
+    TCompactInputProtocol, TCompactInputProtocolFactory, TCompactOutputProtocol,
+    TCompactOutputProtocolFactory,
+};
 pub use self::multiplexed::TMultiplexedOutputProtocol;
 pub use self::stored::TStoredInputProtocol;
 
@@ -186,14 +186,10 @@
     /// Skip a field with type `field_type` recursively up to `depth` levels.
     fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> ::Result<()> {
         if depth == 0 {
-            return Err(
-                ::Error::Protocol(
-                    ProtocolError {
-                        kind: ProtocolErrorKind::DepthLimit,
-                        message: format!("cannot parse past {:?}", field_type),
-                    },
-                ),
-            );
+            return Err(::Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::DepthLimit,
+                message: format!("cannot parse past {:?}", field_type),
+            }));
         }
 
         match field_type {
@@ -243,16 +239,10 @@
                 }
                 self.read_map_end()
             }
-            u => {
-                Err(
-                    ::Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::Unknown,
-                            message: format!("cannot skip field type {:?}", &u),
-                        },
-                    ),
-                )
-            }
+            u => Err(::Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::Unknown,
+                message: format!("cannot skip field type {:?}", &u),
+            })),
         }
     }
 
@@ -787,16 +777,10 @@
             0x02 => Ok(TMessageType::Reply),
             0x03 => Ok(TMessageType::Exception),
             0x04 => Ok(TMessageType::OneWay),
-            unkn => {
-                Err(
-                    ::Error::Protocol(
-                        ProtocolError {
-                            kind: ProtocolErrorKind::InvalidData,
-                            message: format!("cannot convert {} to TMessageType", unkn),
-                        },
-                    ),
-                )
-            }
+            unkn => Err(::Error::Protocol(ProtocolError {
+                kind: ProtocolErrorKind::InvalidData,
+                message: format!("cannot convert {} to TMessageType", unkn),
+            })),
         }
     }
 }
@@ -869,14 +853,10 @@
     if expected == actual {
         Ok(())
     } else {
-        Err(
-            ::Error::Application(
-                ::ApplicationError {
-                    kind: ::ApplicationErrorKind::BadSequenceId,
-                    message: format!("expected {} got {}", expected, actual),
-                },
-            ),
-        )
+        Err(::Error::Application(::ApplicationError {
+            kind: ::ApplicationErrorKind::BadSequenceId,
+            message: format!("expected {} got {}", expected, actual),
+        }))
     }
 }
 
@@ -888,14 +868,10 @@
     if expected == actual {
         Ok(())
     } else {
-        Err(
-            ::Error::Application(
-                ::ApplicationError {
-                    kind: ::ApplicationErrorKind::WrongMethodName,
-                    message: format!("expected {} got {}", expected, actual),
-                },
-            ),
-        )
+        Err(::Error::Application(::ApplicationError {
+            kind: ::ApplicationErrorKind::WrongMethodName,
+            message: format!("expected {} got {}", expected, actual),
+        }))
     }
 }
 
@@ -907,14 +883,10 @@
     if expected == actual {
         Ok(())
     } else {
-        Err(
-            ::Error::Application(
-                ::ApplicationError {
-                    kind: ::ApplicationErrorKind::InvalidMessageType,
-                    message: format!("expected {} got {}", expected, actual),
-                },
-            ),
-        )
+        Err(::Error::Application(::ApplicationError {
+            kind: ::ApplicationErrorKind::InvalidMessageType,
+            message: format!("expected {} got {}", expected, actual),
+        }))
     }
 }
 
@@ -924,16 +896,10 @@
 pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> ::Result<()> {
     match *field {
         Some(_) => Ok(()),
-        None => {
-            Err(
-                ::Error::Protocol(
-                    ::ProtocolError {
-                        kind: ::ProtocolErrorKind::Unknown,
-                        message: format!("missing required field {}", field_name),
-                    },
-                ),
-            )
-        }
+        None => Err(::Error::Protocol(::ProtocolError {
+            kind: ::ProtocolErrorKind::Unknown,
+            message: format!("missing required field {}", field_name),
+        })),
     }
 }
 
@@ -943,18 +909,12 @@
 ///
 /// Return `TFieldIdentifier.id` if an id exists, `Err` otherwise.
 pub fn field_id(field_ident: &TFieldIdentifier) -> ::Result<i16> {
-    field_ident
-        .id
-        .ok_or_else(
-            || {
-                ::Error::Protocol(
-                    ::ProtocolError {
-                        kind: ::ProtocolErrorKind::Unknown,
-                        message: format!("missing field in in {:?}", field_ident),
-                    },
-                )
-            },
-        )
+    field_ident.id.ok_or_else(|| {
+        ::Error::Protocol(::ProtocolError {
+            kind: ::ProtocolErrorKind::Unknown,
+            message: format!("missing field in in {:?}", field_ident),
+        })
+    })
 }
 
 #[cfg(test)]
diff --git a/lib/rs/src/protocol/multiplexed.rs b/lib/rs/src/protocol/multiplexed.rs
index db08027..aaee44f 100644
--- a/lib/rs/src/protocol/multiplexed.rs
+++ b/lib/rs/src/protocol/multiplexed.rs
@@ -15,8 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use super::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType,
-            TOutputProtocol, TSetIdentifier, TStructIdentifier};
+use super::{
+    TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType,
+    TOutputProtocol, TSetIdentifier, TStructIdentifier,
+};
 
 /// `TOutputProtocol` that prefixes the service name to all outgoing Thrift
 /// messages.
@@ -81,7 +83,8 @@
     P: TOutputProtocol,
 {
     fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> {
-        match identifier.message_type { // FIXME: is there a better way to override identifier here?
+        match identifier.message_type {
+            // FIXME: is there a better way to override identifier here?
             TMessageType::Call | TMessageType::OneWay => {
                 let identifier = TMessageIdentifier {
                     name: format!("{}:{}", self.service_name, identifier.name),
@@ -200,6 +203,7 @@
         let ident = TMessageIdentifier::new("bar", TMessageType::Call, 2);
         assert_success!(o_prot.write_message_begin(&ident));
 
+        #[cfg_attr(rustfmt, rustfmt::skip)]
         let expected: [u8; 19] = [
             0x80,
             0x01, /* protocol identifier */
@@ -225,9 +229,7 @@
         assert_eq!(o_prot.inner.transport.write_bytes(), expected);
     }
 
-    fn test_objects
-        ()
-        -> TMultiplexedOutputProtocol<TBinaryOutputProtocol<WriteHalf<TBufferChannel>>>
+    fn test_objects() -> TMultiplexedOutputProtocol<TBinaryOutputProtocol<WriteHalf<TBufferChannel>>>
     {
         let c = TBufferChannel::with_capacity(40, 40);
         let (_, w_chan) = c.split().unwrap();
diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs
index b3f305f..8c55978 100644
--- a/lib/rs/src/protocol/stored.rs
+++ b/lib/rs/src/protocol/stored.rs
@@ -17,9 +17,11 @@
 
 use std::convert::Into;
 
+use super::{
+    TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
+    TSetIdentifier, TStructIdentifier,
+};
 use ProtocolErrorKind;
-use super::{TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier,
-            TSetIdentifier, TStructIdentifier};
 
 /// `TInputProtocol` required to use a `TMultiplexedProcessor`.
 ///
@@ -101,16 +103,12 @@
 
 impl<'a> TInputProtocol for TStoredInputProtocol<'a> {
     fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> {
-        self.message_ident
-            .take()
-            .ok_or_else(
-                || {
-                    ::errors::new_protocol_error(
-                        ProtocolErrorKind::Unknown,
-                        "message identifier already read",
-                    )
-                },
+        self.message_ident.take().ok_or_else(|| {
+            ::errors::new_protocol_error(
+                ProtocolErrorKind::Unknown,
+                "message identifier already read",
             )
+        })
     }
 
     fn read_message_end(&mut self) -> ::Result<()> {
diff --git a/lib/rs/src/server/mod.rs b/lib/rs/src/server/mod.rs
index 3d8ccb2..70b381a 100644
--- a/lib/rs/src/server/mod.rs
+++ b/lib/rs/src/server/mod.rs
@@ -17,8 +17,8 @@
 
 //! Types used to implement a Thrift server.
 
-use {ApplicationError, ApplicationErrorKind};
 use protocol::{TInputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol};
+use {ApplicationError, ApplicationErrorKind};
 
 mod multiplexed;
 mod threaded;
diff --git a/lib/rs/src/server/multiplexed.rs b/lib/rs/src/server/multiplexed.rs
index a7f6d04..e433794 100644
--- a/lib/rs/src/server/multiplexed.rs
+++ b/lib/rs/src/server/multiplexed.rs
@@ -16,16 +16,17 @@
 // under the License.
 
 use std::collections::HashMap;
+use std::convert::Into;
 use std::fmt;
 use std::fmt::{Debug, Formatter};
-use std::convert::Into;
 use std::sync::{Arc, Mutex};
 
 use protocol::{TInputProtocol, TMessageIdentifier, TOutputProtocol, TStoredInputProtocol};
 
-use super::{TProcessor, handle_process_result};
+use super::{handle_process_result, TProcessor};
 
-const MISSING_SEPARATOR_AND_NO_DEFAULT: &'static str = "missing service separator and no default processor set";
+const MISSING_SEPARATOR_AND_NO_DEFAULT: &'static str =
+    "missing service separator and no default processor set";
 type ThreadSafeProcessor = Box<TProcessor + Send + Sync>;
 
 /// A `TProcessor` that can demux service calls to multiple underlying
@@ -54,12 +55,10 @@
     /// processors.
     pub fn new() -> TMultiplexedProcessor {
         TMultiplexedProcessor {
-            stored: Mutex::new(
-                StoredProcessors {
-                    processors: HashMap::new(),
-                    default_processor: None,
-                },
-            ),
+            stored: Mutex::new(StoredProcessors {
+                processors: HashMap::new(),
+                default_processor: None,
+            }),
         }
     }
 
@@ -97,7 +96,7 @@
                 Ok(())
             }
         } else {
-            Err(format!("cannot overwrite existing processor for service {}", name).into(),)
+            Err(format!("cannot overwrite existing processor for service {}", name).into())
         }
     }
 
@@ -160,13 +159,11 @@
 fn split_ident_name(ident_name: &str) -> (Option<&str>, &str) {
     ident_name
         .find(':')
-        .map(
-            |pos| {
-                let (svc_name, svc_call) = ident_name.split_at(pos);
-                let (_, svc_call) = svc_call.split_at(1); // remove colon from service call name
-                (Some(svc_name), svc_call)
-            },
-        )
+        .map(|pos| {
+            let (svc_name, svc_call) = ident_name.split_at(pos);
+            let (_, svc_call) = svc_call.split_at(1); // remove colon from service call name
+            (Some(svc_name), svc_call)
+        })
         .or_else(|| Some((None, ident_name)))
         .unwrap()
 }
@@ -181,12 +178,12 @@
 #[cfg(test)]
 mod tests {
     use std::convert::Into;
-    use std::sync::Arc;
     use std::sync::atomic::{AtomicBool, Ordering};
+    use std::sync::Arc;
 
-    use {ApplicationError, ApplicationErrorKind};
     use protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TMessageIdentifier, TMessageType};
     use transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf};
+    use {ApplicationError, ApplicationErrorKind};
 
     use super::*;
 
@@ -219,8 +216,7 @@
         let p = TMultiplexedProcessor::new();
         p.process(&mut i, &mut o).unwrap(); // at this point an error should be written out
 
-        i.transport
-            .set_readable_bytes(&o.transport.write_bytes());
+        i.transport.set_readable_bytes(&o.transport.write_bytes());
         let rcvd_ident = i.read_message_begin().unwrap();
         let expected_ident = TMessageIdentifier::new("foo", TMessageType::Exception, 10);
         assert_eq!(rcvd_ident, expected_ident);
@@ -245,8 +241,7 @@
         let p = TMultiplexedProcessor::new();
         p.process(&mut i, &mut o).unwrap(); // at this point an error should be written out
 
-        i.transport
-            .set_readable_bytes(&o.transport.write_bytes());
+        i.transport.set_readable_bytes(&o.transport.write_bytes());
         let rcvd_ident = i.read_message_begin().unwrap();
         let expected_ident = TMessageIdentifier::new("missing:call", TMessageType::Exception, 10);
         assert_eq!(rcvd_ident, expected_ident);
@@ -265,7 +260,8 @@
 
     impl TProcessor for Service {
         fn process(&self, _: &mut TInputProtocol, _: &mut TOutputProtocol) -> ::Result<()> {
-            let res = self.invoked
+            let res = self
+                .invoked
                 .compare_and_swap(false, true, Ordering::Relaxed);
             if res {
                 Ok(())
@@ -280,9 +276,13 @@
         let (mut i, mut o) = build_objects();
 
         // build the services
-        let svc_1 = Service { invoked: Arc::new(AtomicBool::new(false)) };
+        let svc_1 = Service {
+            invoked: Arc::new(AtomicBool::new(false)),
+        };
         let atm_1 = svc_1.invoked.clone();
-        let svc_2 = Service { invoked: Arc::new(AtomicBool::new(false)) };
+        let svc_2 = Service {
+            invoked: Arc::new(AtomicBool::new(false)),
+        };
         let atm_2 = svc_2.invoked.clone();
 
         // register them
@@ -309,9 +309,13 @@
         let (mut i, mut o) = build_objects();
 
         // build the services
-        let svc_1 = Service { invoked: Arc::new(AtomicBool::new(false)) };
+        let svc_1 = Service {
+            invoked: Arc::new(AtomicBool::new(false)),
+        };
         let atm_1 = svc_1.invoked.clone();
-        let svc_2 = Service { invoked: Arc::new(AtomicBool::new(false)) };
+        let svc_2 = Service {
+            invoked: Arc::new(AtomicBool::new(false)),
+        };
         let atm_2 = svc_2.invoked.clone();
 
         // register them
@@ -333,12 +337,15 @@
         assert_eq!(atm_2.load(Ordering::Relaxed), true);
     }
 
-    fn build_objects()
-        -> (TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
-            TBinaryOutputProtocol<WriteHalf<TBufferChannel>>)
-    {
+    fn build_objects() -> (
+        TBinaryInputProtocol<ReadHalf<TBufferChannel>>,
+        TBinaryOutputProtocol<WriteHalf<TBufferChannel>>,
+    ) {
         let c = TBufferChannel::with_capacity(128, 128);
         let (r_c, w_c) = c.split().unwrap();
-        (TBinaryInputProtocol::new(r_c, true), TBinaryOutputProtocol::new(w_c, true))
+        (
+            TBinaryInputProtocol::new(r_c, true),
+            TBinaryOutputProtocol::new(w_c, true),
+        )
     }
 }
diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs
index 515b20d..8139a4e 100644
--- a/lib/rs/src/server/threaded.rs
+++ b/lib/rs/src/server/threaded.rs
@@ -19,9 +19,9 @@
 use std::sync::Arc;
 use threadpool::ThreadPool;
 
-use {ApplicationError, ApplicationErrorKind};
 use protocol::{TInputProtocol, TInputProtocolFactory, TOutputProtocol, TOutputProtocolFactory};
 use transport::{TIoChannel, TReadTransportFactory, TTcpChannel, TWriteTransportFactory};
+use {ApplicationError, ApplicationErrorKind};
 
 use super::TProcessor;
 
@@ -129,11 +129,13 @@
 }
 
 impl<PRC, RTF, IPF, WTF, OPF> TServer<PRC, RTF, IPF, WTF, OPF>
-    where PRC: TProcessor + Send + Sync + 'static,
-          RTF: TReadTransportFactory + 'static,
-          IPF: TInputProtocolFactory + 'static,
-          WTF: TWriteTransportFactory + 'static,
-          OPF: TOutputProtocolFactory + 'static {
+where
+    PRC: TProcessor + Send + Sync + 'static,
+    RTF: TReadTransportFactory + 'static,
+    IPF: TInputProtocolFactory + 'static,
+    WTF: TWriteTransportFactory + 'static,
+    OPF: TOutputProtocolFactory + 'static,
+{
     /// Create a `TServer`.
     ///
     /// Each accepted connection has an input and output half, each of which
@@ -155,10 +157,7 @@
             w_trans_factory: write_transport_factory,
             o_proto_factory: output_protocol_factory,
             processor: Arc::new(processor),
-            worker_pool: ThreadPool::with_name(
-                "Thrift service processor".to_owned(),
-                num_workers,
-            ),
+            worker_pool: ThreadPool::with_name("Thrift service processor".to_owned(), num_workers),
         }
     }
 
@@ -179,7 +178,7 @@
                     let (i_prot, o_prot) = self.new_protocols_for_connection(s)?;
                     let processor = self.processor.clone();
                     self.worker_pool
-                        .execute(move || handle_incoming_connection(processor, i_prot, o_prot),);
+                        .execute(move || handle_incoming_connection(processor, i_prot, o_prot));
                 }
                 Err(e) => {
                     warn!("failed to accept remote connection with error {:?}", e);
@@ -187,17 +186,12 @@
             }
         }
 
-        Err(
-            ::Error::Application(
-                ApplicationError {
-                    kind: ApplicationErrorKind::Unknown,
-                    message: "aborted listen loop".into(),
-                },
-            ),
-        )
+        Err(::Error::Application(ApplicationError {
+            kind: ApplicationErrorKind::Unknown,
+            message: "aborted listen loop".into(),
+        }))
     }
 
-
     fn new_protocols_for_connection(
         &mut self,
         stream: TcpStream,
diff --git a/lib/rs/src/transport/buffered.rs b/lib/rs/src/transport/buffered.rs
index b588ec1..87cfeff 100644
--- a/lib/rs/src/transport/buffered.rs
+++ b/lib/rs/src/transport/buffered.rs
@@ -174,6 +174,7 @@
     C: Write,
 {
     buf: Vec<u8>,
+    cap: usize,
     channel: C,
 }
 
@@ -191,8 +192,14 @@
     /// `read_capacity` and an internal write buffer of size
     /// `write_capacity` that wraps the given `TIoChannel`.
     pub fn with_capacity(write_capacity: usize, channel: C) -> TBufferedWriteTransport<C> {
+        assert!(
+            write_capacity > 0,
+            "write buffer size must be a positive integer"
+        );
+
         TBufferedWriteTransport {
             buf: Vec::with_capacity(write_capacity),
+            cap: write_capacity,
             channel: channel,
         }
     }
@@ -203,13 +210,28 @@
     C: Write,
 {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let avail_bytes = cmp::min(buf.len(), self.buf.capacity() - self.buf.len());
-        self.buf.extend_from_slice(&buf[..avail_bytes]);
-        assert!(
-            self.buf.len() <= self.buf.capacity(),
-            "copy overflowed buffer"
-        );
-        Ok(avail_bytes)
+        if !buf.is_empty() {
+            let mut avail_bytes;
+
+            loop {
+                avail_bytes = cmp::min(buf.len(), self.cap - self.buf.len());
+
+                if avail_bytes == 0 {
+                    self.flush()?;
+                } else {
+                    break;
+                }
+            }
+
+            let avail_bytes = avail_bytes;
+
+            self.buf.extend_from_slice(&buf[..avail_bytes]);
+            assert!(self.buf.len() <= self.cap, "copy overflowed buffer");
+
+            Ok(avail_bytes)
+        } else {
+            Ok(0)
+        }
     }
 
     fn flush(&mut self) -> io::Result<()> {
@@ -364,14 +386,21 @@
     }
 
     #[test]
-    fn must_return_zero_if_nothing_can_be_written() {
+    fn must_return_error_when_nothing_can_be_written_to_underlying_channel() {
         let mem = TBufferChannel::with_capacity(0, 0);
-        let mut t = TBufferedWriteTransport::with_capacity(0, mem);
+        let mut t = TBufferedWriteTransport::with_capacity(1, mem);
 
         let b = vec![0; 10];
         let r = t.write(&b);
 
-        assert_eq!(r.unwrap(), 0);
+        // should have written 1 byte
+        assert_eq!(r.unwrap(), 1);
+
+        // let's try again...
+        let r = t.write(&b[1..]);
+
+        // this time we'll error out because the auto-flush failed
+        assert!(r.is_err());
     }
 
     #[test]
@@ -387,23 +416,35 @@
     }
 
     #[test]
-    fn must_return_zero_if_write_buffer_full() {
-        let mem = TBufferChannel::with_capacity(0, 0);
+    fn must_auto_flush_if_write_buffer_full() {
+        let mem = TBufferChannel::with_capacity(0, 8);
         let mut t = TBufferedWriteTransport::with_capacity(4, mem);
 
-        let b = [0x00, 0x01, 0x02, 0x03];
+        let b0 = [0x00, 0x01, 0x02, 0x03];
+        let b1 = [0x04, 0x05, 0x06, 0x07];
 
-        // we've now filled the write buffer
-        let r = t.write(&b);
+        // write the first 4 bytes; we've now filled the transport's write buffer
+        let r = t.write(&b0);
         assert_eq!(r.unwrap(), 4);
 
-        // try write the same bytes again - nothing should be writable
-        let r = t.write(&b);
-        assert_eq!(r.unwrap(), 0);
+        // try write the next 4 bytes; this causes the transport to auto-flush the first 4 bytes
+        let r = t.write(&b1);
+        assert_eq!(r.unwrap(), 4);
+
+        // check that in writing the second 4 bytes we auto-flushed the first 4 bytes
+        assert_eq_transport_num_written_bytes!(t, 4);
+        assert_eq_transport_written_bytes!(t, b0);
+        t.channel.empty_write_buffer();
+
+        // now flush the transport to push the second 4 bytes to the underlying channel
+        assert!(t.flush().is_ok());
+
+        // check that we wrote out the second 4 bytes
+        assert_eq_transport_written_bytes!(t, b1);
     }
 
     #[test]
-    fn must_only_write_to_inner_transport_on_flush() {
+    fn must_write_to_inner_transport_on_flush() {
         let mem = TBufferChannel::with_capacity(10, 10);
         let mut t = TBufferedWriteTransport::new(mem);
 
diff --git a/lib/rs/src/transport/framed.rs b/lib/rs/src/transport/framed.rs
index d78d2f7..a009307 100644
--- a/lib/rs/src/transport/framed.rs
+++ b/lib/rs/src/transport/framed.rs
@@ -18,7 +18,7 @@
 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
 use std::cmp;
 use std::io;
-use std::io::{ErrorKind, Read, Write};
+use std::io::{Read, Write};
 
 use super::{TReadTransport, TReadTransportFactory, TWriteTransport, TWriteTransportFactory};
 
@@ -57,7 +57,7 @@
 where
     C: Read,
 {
-    buf: Box<[u8]>,
+    buf: Vec<u8>,
     pos: usize,
     cap: usize,
     chan: C,
@@ -67,18 +67,17 @@
 where
     C: Read,
 {
-    /// Create a `TFramedTransport` with default-sized internal read and
-    /// write buffers that wraps the given `TIoChannel`.
+    /// Create a `TFramedReadTransport` with a default-sized
+    /// internal read buffer that wraps the given `TIoChannel`.
     pub fn new(channel: C) -> TFramedReadTransport<C> {
         TFramedReadTransport::with_capacity(READ_CAPACITY, channel)
     }
 
-    /// Create a `TFramedTransport` with an internal read buffer of size
-    /// `read_capacity` and an internal write buffer of size
-    /// `write_capacity` that wraps the given `TIoChannel`.
+    /// Create a `TFramedTransport` with an internal read buffer
+    /// of size `read_capacity` that wraps the given `TIoChannel`.
     pub fn with_capacity(read_capacity: usize, channel: C) -> TFramedReadTransport<C> {
         TFramedReadTransport {
-            buf: vec![0; read_capacity].into_boxed_slice(),
+            buf: vec![0; read_capacity], // FIXME: do I actually have to do this?
             pos: 0,
             cap: 0,
             chan: channel,
@@ -93,22 +92,13 @@
     fn read(&mut self, b: &mut [u8]) -> io::Result<usize> {
         if self.cap - self.pos == 0 {
             let message_size = self.chan.read_i32::<BigEndian>()? as usize;
-            if message_size > self.buf.len() {
-                return Err(
-                    io::Error::new(
-                        ErrorKind::Other,
-                        format!(
-                            "bytes to be read ({}) exceeds buffer \
-                                                   capacity ({})",
-                            message_size,
-                            self.buf.len()
-                        ),
-                    ),
-                );
-            }
+
+            let buf_capacity = cmp::max(message_size, READ_CAPACITY);
+            self.buf.resize(buf_capacity, 0);
+
             self.chan.read_exact(&mut self.buf[..message_size])?;
-            self.pos = 0;
             self.cap = message_size as usize;
+            self.pos = 0;
         }
 
         let nread = cmp::min(b.len(), self.cap - self.pos);
@@ -165,8 +155,7 @@
 where
     C: Write,
 {
-    buf: Box<[u8]>,
-    pos: usize,
+    buf: Vec<u8>,
     channel: C,
 }
 
@@ -174,20 +163,18 @@
 where
     C: Write,
 {
-    /// Create a `TFramedTransport` with default-sized internal read and
-    /// write buffers that wraps the given `TIoChannel`.
+    /// Create a `TFramedWriteTransport` with default-sized internal
+    /// write buffer that wraps the given `TIoChannel`.
     pub fn new(channel: C) -> TFramedWriteTransport<C> {
         TFramedWriteTransport::with_capacity(WRITE_CAPACITY, channel)
     }
 
-    /// Create a `TFramedTransport` with an internal read buffer of size
-    /// `read_capacity` and an internal write buffer of size
-    /// `write_capacity` that wraps the given `TIoChannel`.
+    /// Create a `TFramedWriteTransport` with an internal write buffer
+    /// of size `write_capacity` that wraps the given `TIoChannel`.
     pub fn with_capacity(write_capacity: usize, channel: C) -> TFramedWriteTransport<C> {
         TFramedWriteTransport {
-            buf: vec![0; write_capacity].into_boxed_slice(),
-            pos: 0,
-            channel: channel,
+            buf: Vec::with_capacity(write_capacity),
+            channel,
         }
     }
 }
@@ -197,43 +184,37 @@
     C: Write,
 {
     fn write(&mut self, b: &[u8]) -> io::Result<usize> {
-        if b.len() > (self.buf.len() - self.pos) {
-            return Err(
-                io::Error::new(
-                    ErrorKind::Other,
-                    format!(
-                        "bytes to be written ({}) exceeds buffer \
-                                               capacity ({})",
-                        b.len(),
-                        self.buf.len() - self.pos
-                    ),
-                ),
-            );
+        let current_capacity = self.buf.capacity();
+        let available_space = current_capacity - self.buf.len();
+        if b.len() > available_space {
+            let additional_space = cmp::max(b.len() - available_space, current_capacity);
+            self.buf.reserve(additional_space);
         }
 
-        let nwrite = b.len(); // always less than available write buffer capacity
-        self.buf[self.pos..(self.pos + nwrite)].clone_from_slice(b);
-        self.pos += nwrite;
-        Ok(nwrite)
+        self.buf.extend_from_slice(b);
+        Ok(b.len())
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        let message_size = self.pos;
+        let message_size = self.buf.len();
 
         if let 0 = message_size {
             return Ok(());
         } else {
-            self.channel
-                .write_i32::<BigEndian>(message_size as i32)?;
+            self.channel.write_i32::<BigEndian>(message_size as i32)?;
         }
 
+        // will spin if the underlying channel can't be written to
         let mut byte_index = 0;
-        while byte_index < self.pos {
-            let nwrite = self.channel.write(&self.buf[byte_index..self.pos])?;
-            byte_index = cmp::min(byte_index + nwrite, self.pos);
+        while byte_index < message_size {
+            let nwrite = self.channel.write(&self.buf[byte_index..message_size])?;
+            byte_index = cmp::min(byte_index + nwrite, message_size);
         }
 
-        self.pos = 0;
+        let buf_capacity = cmp::min(self.buf.capacity(), WRITE_CAPACITY);
+        self.buf.resize(buf_capacity, 0);
+        self.buf.clear();
+
         self.channel.flush()
     }
 }
@@ -257,8 +238,222 @@
 
 #[cfg(test)]
 mod tests {
-    //    use std::io::{Read, Write};
-    //
-    //    use super::*;
-    //    use ::transport::mem::TBufferChannel;
+    use super::*;
+    use transport::mem::TBufferChannel;
+
+    // FIXME: test a forced reserve
+
+    #[test]
+    fn must_read_message_smaller_than_initial_buffer_size() {
+        let c = TBufferChannel::with_capacity(10, 10);
+        let mut t = TFramedReadTransport::with_capacity(8, c);
+
+        t.chan.set_readable_bytes(&[
+            0x00, 0x00, 0x00, 0x04, /* message size */
+            0x00, 0x01, 0x02, 0x03, /* message body */
+        ]);
+
+        let mut buf = vec![0; 8];
+
+        // we've read exactly 4 bytes
+        assert_eq!(t.read(&mut buf).unwrap(), 4);
+        assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]);
+    }
+
+    #[test]
+    fn must_read_message_greater_than_initial_buffer_size() {
+        let c = TBufferChannel::with_capacity(10, 10);
+        let mut t = TFramedReadTransport::with_capacity(2, c);
+
+        t.chan.set_readable_bytes(&[
+            0x00, 0x00, 0x00, 0x04, /* message size */
+            0x00, 0x01, 0x02, 0x03, /* message body */
+        ]);
+
+        let mut buf = vec![0; 8];
+
+        // we've read exactly 4 bytes
+        assert_eq!(t.read(&mut buf).unwrap(), 4);
+        assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]);
+    }
+
+    #[test]
+    fn must_read_multiple_messages_in_sequence_correctly() {
+        let c = TBufferChannel::with_capacity(10, 10);
+        let mut t = TFramedReadTransport::with_capacity(2, c);
+
+        //
+        // 1st message
+        //
+
+        t.chan.set_readable_bytes(&[
+            0x00, 0x00, 0x00, 0x04, /* message size */
+            0x00, 0x01, 0x02, 0x03, /* message body */
+        ]);
+
+        let mut buf = vec![0; 8];
+
+        // we've read exactly 4 bytes
+        assert_eq!(t.read(&mut buf).unwrap(), 4);
+        assert_eq!(&buf, &[0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00]);
+
+        //
+        // 2nd message
+        //
+
+        t.chan.set_readable_bytes(&[
+            0x00, 0x00, 0x00, 0x01, /* message size */
+            0x04, /* message body */
+        ]);
+
+        let mut buf = vec![0; 8];
+
+        // we've read exactly 1 byte
+        assert_eq!(t.read(&mut buf).unwrap(), 1);
+        assert_eq!(&buf, &[0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
+    }
+
+    #[test]
+    fn must_write_message_smaller_than_buffer_size() {
+        let mem = TBufferChannel::with_capacity(0, 0);
+        let mut t = TFramedWriteTransport::with_capacity(20, mem);
+
+        let b = vec![0; 10];
+
+        // should have written 10 bytes
+        assert_eq!(t.write(&b).unwrap(), 10);
+    }
+
+    #[test]
+    fn must_return_zero_if_caller_calls_write_with_empty_buffer() {
+        let mem = TBufferChannel::with_capacity(0, 10);
+        let mut t = TFramedWriteTransport::with_capacity(10, mem);
+
+        let expected: [u8; 0] = [];
+
+        assert_eq!(t.write(&[]).unwrap(), 0);
+        assert_eq_transport_written_bytes!(t, expected);
+    }
+
+    #[test]
+    fn must_write_to_inner_transport_on_flush() {
+        let mem = TBufferChannel::with_capacity(10, 10);
+        let mut t = TFramedWriteTransport::new(mem);
+
+        let b: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04];
+        assert_eq!(t.write(&b).unwrap(), 5);
+        assert_eq_transport_num_written_bytes!(t, 0);
+
+        assert!(t.flush().is_ok());
+
+        let expected_bytes = [
+            0x00, 0x00, 0x00, 0x05, /* message size */
+            0x00, 0x01, 0x02, 0x03, 0x04, /* message body */
+        ];
+
+        assert_eq_transport_written_bytes!(t, expected_bytes);
+    }
+
+    #[test]
+    fn must_write_message_greater_than_buffer_size_00() {
+        let mem = TBufferChannel::with_capacity(0, 10);
+
+        // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN!
+        // these lengths were chosen to be just long enough
+        // that doubling the capacity is a **worse** choice than
+        // simply resizing the buffer to b.len()
+
+        let mut t = TFramedWriteTransport::with_capacity(1, mem);
+        let b = [0x00, 0x01, 0x02];
+
+        // should have written 3 bytes
+        assert_eq!(t.write(&b).unwrap(), 3);
+        assert_eq_transport_num_written_bytes!(t, 0);
+
+        assert!(t.flush().is_ok());
+
+        let expected_bytes = [
+            0x00, 0x00, 0x00, 0x03, /* message size */
+            0x00, 0x01, 0x02, /* message body */
+        ];
+
+        assert_eq_transport_written_bytes!(t, expected_bytes);
+    }
+
+    #[test]
+    fn must_write_message_greater_than_buffer_size_01() {
+        let mem = TBufferChannel::with_capacity(0, 10);
+
+        // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN!
+        // these lengths were chosen to be just long enough
+        // that doubling the capacity is a **better** choice than
+        // simply resizing the buffer to b.len()
+
+        let mut t = TFramedWriteTransport::with_capacity(2, mem);
+        let b = [0x00, 0x01, 0x02];
+
+        // should have written 3 bytes
+        assert_eq!(t.write(&b).unwrap(), 3);
+        assert_eq_transport_num_written_bytes!(t, 0);
+
+        assert!(t.flush().is_ok());
+
+        let expected_bytes = [
+            0x00, 0x00, 0x00, 0x03, /* message size */
+            0x00, 0x01, 0x02, /* message body */
+        ];
+
+        assert_eq_transport_written_bytes!(t, expected_bytes);
+    }
+
+    #[test]
+    fn must_return_error_if_nothing_can_be_written_to_inner_transport_on_flush() {
+        let mem = TBufferChannel::with_capacity(0, 0);
+        let mut t = TFramedWriteTransport::with_capacity(1, mem);
+
+        let b = vec![0; 10];
+
+        // should have written 10 bytes
+        assert_eq!(t.write(&b).unwrap(), 10);
+
+        // let's flush
+        let r = t.flush();
+
+        // this time we'll error out because the flush can't write to the underlying channel
+        assert!(r.is_err());
+    }
+
+    #[test]
+    fn must_write_successfully_after_flush() {
+        // IMPORTANT: write capacity *MUST* be greater
+        // than message sizes used in this test + 4-byte frame header
+        let mem = TBufferChannel::with_capacity(0, 10);
+        let mut t = TFramedWriteTransport::with_capacity(5, mem);
+
+        // write and flush
+        let first_message: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04];
+        assert_eq!(t.write(&first_message).unwrap(), 5);
+        assert!(t.flush().is_ok());
+
+        let mut expected = Vec::new();
+        expected.write_all(&[0x00, 0x00, 0x00, 0x05]).unwrap(); // message size
+        expected.extend_from_slice(&first_message);
+
+        // check the flushed bytes
+        assert_eq!(t.channel.write_bytes(), expected);
+
+        // reset our underlying transport
+        t.channel.empty_write_buffer();
+
+        let second_message: [u8; 3] = [0x05, 0x06, 0x07];
+        assert_eq!(t.write(&second_message).unwrap(), 3);
+        assert!(t.flush().is_ok());
+
+        expected.clear();
+        expected.write_all(&[0x00, 0x00, 0x00, 0x03]).unwrap(); // message size
+        expected.extend_from_slice(&second_message);
+
+        // check the flushed bytes
+        assert_eq!(t.channel.write_bytes(), expected);
+    }
 }
diff --git a/lib/rs/src/transport/mem.rs b/lib/rs/src/transport/mem.rs
index 86ac6bb..82c4b57 100644
--- a/lib/rs/src/transport/mem.rs
+++ b/lib/rs/src/transport/mem.rs
@@ -57,25 +57,17 @@
     /// read buffer capacity and write buffer capacity.
     pub fn with_capacity(read_capacity: usize, write_capacity: usize) -> TBufferChannel {
         TBufferChannel {
-            read: Arc::new(
-                Mutex::new(
-                    ReadData {
-                        buf: vec![0; read_capacity].into_boxed_slice(),
-                        idx: 0,
-                        pos: 0,
-                        cap: read_capacity,
-                    },
-                ),
-            ),
-            write: Arc::new(
-                Mutex::new(
-                    WriteData {
-                        buf: vec![0; write_capacity].into_boxed_slice(),
-                        pos: 0,
-                        cap: write_capacity,
-                    },
-                ),
-            ),
+            read: Arc::new(Mutex::new(ReadData {
+                buf: vec![0; read_capacity].into_boxed_slice(),
+                idx: 0,
+                pos: 0,
+                cap: read_capacity,
+            })),
+            write: Arc::new(Mutex::new(WriteData {
+                buf: vec![0; write_capacity].into_boxed_slice(),
+                pos: 0,
+                cap: write_capacity,
+            })),
         }
     }
 
@@ -151,20 +143,20 @@
     where
         Self: Sized,
     {
-        Ok(
-            (ReadHalf {
-                 handle: TBufferChannel {
-                     read: self.read.clone(),
-                     write: self.write.clone(),
-                 },
-             },
-             WriteHalf {
-                 handle: TBufferChannel {
-                     read: self.read.clone(),
-                     write: self.write.clone(),
-                 },
-             }),
-        )
+        Ok((
+            ReadHalf {
+                handle: TBufferChannel {
+                    read: self.read.clone(),
+                    write: self.write.clone(),
+                },
+            },
+            WriteHalf {
+                handle: TBufferChannel {
+                    read: self.read.clone(),
+                    write: self.write.clone(),
+                },
+            },
+        ))
     }
 }
 
diff --git a/lib/rs/src/transport/mod.rs b/lib/rs/src/transport/mod.rs
index 9392786..a623350 100644
--- a/lib/rs/src/transport/mod.rs
+++ b/lib/rs/src/transport/mod.rs
@@ -29,32 +29,31 @@
 
 #[cfg(test)]
 macro_rules! assert_eq_transport_num_written_bytes {
-    ($transport:ident, $num_written_bytes:expr) => {
-        {
-            assert_eq!($transport.channel.write_bytes().len(), $num_written_bytes);
-        }
-    };
+    ($transport:ident, $num_written_bytes:expr) => {{
+        assert_eq!($transport.channel.write_bytes().len(), $num_written_bytes);
+    }};
 }
 
-
 #[cfg(test)]
 macro_rules! assert_eq_transport_written_bytes {
-    ($transport:ident, $expected_bytes:ident) => {
-        {
-            assert_eq!($transport.channel.write_bytes(), &$expected_bytes);
-        }
-    };
+    ($transport:ident, $expected_bytes:ident) => {{
+        assert_eq!($transport.channel.write_bytes(), &$expected_bytes);
+    }};
 }
 
 mod buffered;
 mod framed;
-mod socket;
 mod mem;
+mod socket;
 
-pub use self::buffered::{TBufferedReadTransport, TBufferedReadTransportFactory,
-                         TBufferedWriteTransport, TBufferedWriteTransportFactory};
-pub use self::framed::{TFramedReadTransport, TFramedReadTransportFactory, TFramedWriteTransport,
-                       TFramedWriteTransportFactory};
+pub use self::buffered::{
+    TBufferedReadTransport, TBufferedReadTransportFactory, TBufferedWriteTransport,
+    TBufferedWriteTransportFactory,
+};
+pub use self::framed::{
+    TFramedReadTransport, TFramedReadTransportFactory, TFramedWriteTransport,
+    TFramedWriteTransportFactory,
+};
 pub use self::mem::TBufferChannel;
 pub use self::socket::TTcpChannel;
 
@@ -78,17 +77,9 @@
     fn create(&self, channel: Box<Write + Send>) -> Box<TWriteTransport + Send>;
 }
 
-impl<T> TReadTransport for T
-where
-    T: Read,
-{
-}
+impl<T> TReadTransport for T where T: Read {}
 
-impl<T> TWriteTransport for T
-where
-    T: Write,
-{
-}
+impl<T> TWriteTransport for T where T: Write {}
 
 // FIXME: implement the Debug trait for boxed transports
 
@@ -143,6 +134,26 @@
     handle: C,
 }
 
+impl<C> ReadHalf<C>
+where
+    C: Read,
+{
+    /// Create a `ReadHalf` associated with readable `handle`
+    pub fn new(handle: C) -> ReadHalf<C> {
+        ReadHalf { handle }
+    }
+}
+
+impl<C> WriteHalf<C>
+where
+    C: Write,
+{
+    /// Create a `WriteHalf` associated with writable `handle`
+    pub fn new(handle: C) -> WriteHalf<C> {
+        WriteHalf { handle }
+    }
+}
+
 impl<C> Read for ReadHalf<C>
 where
     C: Read,
diff --git a/lib/rs/src/transport/socket.rs b/lib/rs/src/transport/socket.rs
index 727bba3..0bef67b 100644
--- a/lib/rs/src/transport/socket.rs
+++ b/lib/rs/src/transport/socket.rs
@@ -20,8 +20,8 @@
 use std::io::{ErrorKind, Read, Write};
 use std::net::{Shutdown, TcpStream};
 
-use {TransportErrorKind, new_transport_error};
 use super::{ReadHalf, TIoChannel, WriteHalf};
+use {new_transport_error, TransportErrorKind};
 
 /// Bidirectional TCP/IP channel.
 ///
@@ -76,18 +76,18 @@
     /// The passed-in stream is assumed to have been opened before being wrapped
     /// by the created `TTcpChannel` instance.
     pub fn with_stream(stream: TcpStream) -> TTcpChannel {
-        TTcpChannel { stream: Some(stream) }
+        TTcpChannel {
+            stream: Some(stream),
+        }
     }
 
     /// Connect to `remote_address`, which should have the form `host:port`.
     pub fn open(&mut self, remote_address: &str) -> ::Result<()> {
         if self.stream.is_some() {
-            Err(
-                new_transport_error(
-                    TransportErrorKind::AlreadyOpen,
-                    "tcp connection previously opened",
-                ),
-            )
+            Err(new_transport_error(
+                TransportErrorKind::AlreadyOpen,
+                "tcp connection previously opened",
+            ))
         } else {
             match TcpStream::connect(&remote_address) {
                 Ok(s) => {
@@ -112,11 +112,13 @@
     where
         F: FnMut(&mut TcpStream) -> io::Result<T>,
     {
-
         if let Some(ref mut s) = self.stream {
             stream_operation(s)
         } else {
-            Err(io::Error::new(ErrorKind::NotConnected, "tcp endpoint not connected"),)
+            Err(io::Error::new(
+                ErrorKind::NotConnected,
+                "tcp endpoint not connected",
+            ))
         }
     }
 }
@@ -131,20 +133,21 @@
         s.stream
             .as_mut()
             .and_then(|s| s.try_clone().ok())
-            .map(
-                |cloned| {
-                    (ReadHalf { handle: TTcpChannel { stream: s.stream.take() } },
-                     WriteHalf { handle: TTcpChannel { stream: Some(cloned) } })
-                },
-            )
-            .ok_or_else(
-                || {
-                    new_transport_error(
-                        TransportErrorKind::Unknown,
-                        "cannot clone underlying tcp stream",
-                    )
-                },
-            )
+            .map(|cloned| {
+                let read_half = ReadHalf::new(TTcpChannel {
+                    stream: s.stream.take(),
+                });
+                let write_half = WriteHalf::new(TTcpChannel {
+                    stream: Some(cloned),
+                });
+                (read_half, write_half)
+            })
+            .ok_or_else(|| {
+                new_transport_error(
+                    TransportErrorKind::Unknown,
+                    "cannot clone underlying tcp stream",
+                )
+            })
     }
 }
 
@@ -156,7 +159,7 @@
 
 impl Write for TTcpChannel {
     fn write(&mut self, b: &[u8]) -> io::Result<usize> {
-        self.if_set(|s| s.write_all(b)).map(|_| b.len())
+        self.if_set(|s| s.write(b))
     }
 
     fn flush(&mut self) -> io::Result<()> {
diff --git a/lib/rs/test/src/bin/kitchen_sink_client.rs b/lib/rs/test/src/bin/kitchen_sink_client.rs
index fb6ea15..d295c88 100644
--- a/lib/rs/test/src/bin/kitchen_sink_client.rs
+++ b/lib/rs/test/src/bin/kitchen_sink_client.rs
@@ -28,10 +28,13 @@
 use kitchen_sink::recursive;
 use kitchen_sink::recursive::{CoRec, CoRec2, RecList, RecTree, TTestServiceSyncClient};
 use kitchen_sink::ultimate::{FullMealServiceSyncClient, TFullMealServiceSyncClient};
-use thrift::transport::{ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel,
-                        TTcpChannel, WriteHalf};
-use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol,
-                       TCompactOutputProtocol, TInputProtocol, TOutputProtocol};
+use thrift::protocol::{
+    TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol,
+    TInputProtocol, TOutputProtocol,
+};
+use thrift::transport::{
+    ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel, WriteHalf,
+};
 
 fn main() {
     match run() {
@@ -61,17 +64,20 @@
     let service = matches.value_of("service").unwrap_or("part");
 
     let (i_chan, o_chan) = tcp_channel(host, port)?;
-    let (i_tran, o_tran) = (TFramedReadTransport::new(i_chan), TFramedWriteTransport::new(o_chan));
+    let (i_tran, o_tran) = (
+        TFramedReadTransport::new(i_chan),
+        TFramedWriteTransport::new(o_chan),
+    );
 
     let (i_prot, o_prot): (Box<TInputProtocol>, Box<TOutputProtocol>) = match protocol {
-        "binary" => {
-            (Box::new(TBinaryInputProtocol::new(i_tran, true)),
-             Box::new(TBinaryOutputProtocol::new(o_tran, true)))
-        }
-        "compact" => {
-            (Box::new(TCompactInputProtocol::new(i_tran)),
-             Box::new(TCompactOutputProtocol::new(o_tran)))
-        }
+        "binary" => (
+            Box::new(TBinaryInputProtocol::new(i_tran, true)),
+            Box::new(TBinaryOutputProtocol::new(o_tran, true)),
+        ),
+        "compact" => (
+            Box::new(TCompactInputProtocol::new(i_tran)),
+            Box::new(TCompactOutputProtocol::new(o_tran)),
+        ),
         unmatched => return Err(format!("unsupported protocol {}", unmatched).into()),
     };
 
@@ -87,7 +93,10 @@
         "full" => exec_full_meal_client(i_prot, o_prot),
         "part" => exec_meal_client(i_prot, o_prot),
         "recursive" => exec_recursive_client(i_prot, o_prot),
-        _ => Err(thrift::Error::from(format!("unknown service type {}", service)),),
+        _ => Err(thrift::Error::from(format!(
+            "unknown service type {}",
+            service
+        ))),
     }
 }
 
@@ -110,12 +119,9 @@
     // this is because the MealService struct does not contain the appropriate service marker
 
     // only the following three calls work
-    execute_call("part", "ramen", || client.ramen(50))
-        .map(|_| ())?;
-    execute_call("part", "meal", || client.meal())
-        .map(|_| ())?;
-    execute_call("part", "napkin", || client.napkin())
-        .map(|_| ())?;
+    execute_call("part", "ramen", || client.ramen(50)).map(|_| ())?;
+    execute_call("part", "meal", || client.meal()).map(|_| ())?;
+    execute_call("part", "napkin", || client.napkin()).map(|_| ())?;
 
     Ok(())
 }
@@ -126,14 +132,10 @@
 ) -> thrift::Result<()> {
     let mut client = FullMealServiceSyncClient::new(i_prot, o_prot);
 
-    execute_call("full", "ramen", || client.ramen(100))
-        .map(|_| ())?;
-    execute_call("full", "meal", || client.meal())
-        .map(|_| ())?;
-    execute_call("full", "napkin", || client.napkin())
-        .map(|_| ())?;
-    execute_call("full", "full meal", || client.full_meal())
-        .map(|_| ())?;
+    execute_call("full", "ramen", || client.ramen(100)).map(|_| ())?;
+    execute_call("full", "meal", || client.meal()).map(|_| ())?;
+    execute_call("full", "napkin", || client.napkin()).map(|_| ())?;
+    execute_call("full", "full meal", || client.full_meal()).map(|_| ())?;
 
     Ok(())
 }
@@ -145,114 +147,75 @@
     let mut client = recursive::TestServiceSyncClient::new(i_prot, o_prot);
 
     let tree = RecTree {
-        children: Some(
-            vec![
-                Box::new(
-                    RecTree {
-                        children: Some(
-                            vec![
-                                Box::new(
-                                    RecTree {
-                                        children: None,
-                                        item: Some(3),
-                                    },
-                                ),
-                                Box::new(
-                                    RecTree {
-                                        children: None,
-                                        item: Some(4),
-                                    },
-                                ),
-                            ],
-                        ),
-                        item: Some(2),
-                    },
-                ),
-            ],
-        ),
+        children: Some(vec![Box::new(RecTree {
+            children: Some(vec![
+                Box::new(RecTree {
+                    children: None,
+                    item: Some(3),
+                }),
+                Box::new(RecTree {
+                    children: None,
+                    item: Some(4),
+                }),
+            ]),
+            item: Some(2),
+        })]),
         item: Some(1),
     };
 
     let expected_tree = RecTree {
-        children: Some(
-            vec![
-                Box::new(
-                    RecTree {
-                        children: Some(
-                            vec![
-                                Box::new(
-                                    RecTree {
-                                        children: Some(Vec::new()), // remote returns an empty list
-                                        item: Some(3),
-                                    },
-                                ),
-                                Box::new(
-                                    RecTree {
-                                        children: Some(Vec::new()), // remote returns an empty list
-                                        item: Some(4),
-                                    },
-                                ),
-                            ],
-                        ),
-                        item: Some(2),
-                    },
-                ),
-            ],
-        ),
+        children: Some(vec![Box::new(RecTree {
+            children: Some(vec![
+                Box::new(RecTree {
+                    children: Some(Vec::new()), // remote returns an empty list
+                    item: Some(3),
+                }),
+                Box::new(RecTree {
+                    children: Some(Vec::new()), // remote returns an empty list
+                    item: Some(4),
+                }),
+            ]),
+            item: Some(2),
+        })]),
         item: Some(1),
     };
 
     let returned_tree = execute_call("recursive", "echo_tree", || client.echo_tree(tree.clone()))?;
     if returned_tree != expected_tree {
-        return Err(
-            format!(
-                "mismatched recursive tree {:?} {:?}",
-                expected_tree,
-                returned_tree
-            )
-                    .into(),
-        );
+        return Err(format!(
+            "mismatched recursive tree {:?} {:?}",
+            expected_tree, returned_tree
+        )
+        .into());
     }
 
     let list = RecList {
-        nextitem: Some(
-            Box::new(
-                RecList {
-                    nextitem: Some(
-                        Box::new(
-                            RecList {
-                                nextitem: None,
-                                item: Some(3),
-                            },
-                        ),
-                    ),
-                    item: Some(2),
-                },
-            ),
-        ),
+        nextitem: Some(Box::new(RecList {
+            nextitem: Some(Box::new(RecList {
+                nextitem: None,
+                item: Some(3),
+            })),
+            item: Some(2),
+        })),
         item: Some(1),
     };
     let returned_list = execute_call("recursive", "echo_list", || client.echo_list(list.clone()))?;
     if returned_list != list {
-        return Err(format!("mismatched recursive list {:?} {:?}", list, returned_list).into(),);
+        return Err(format!("mismatched recursive list {:?} {:?}", list, returned_list).into());
     }
 
     let co_rec = CoRec {
-        other: Some(
-            Box::new(
-                CoRec2 {
-                    other: Some(CoRec { other: Some(Box::new(CoRec2 { other: None })) }),
-                },
-            ),
-        ),
+        other: Some(Box::new(CoRec2 {
+            other: Some(CoRec {
+                other: Some(Box::new(CoRec2 { other: None })),
+            }),
+        })),
     };
-    let returned_co_rec = execute_call(
-        "recursive",
-        "echo_co_rec",
-        || client.echo_co_rec(co_rec.clone()),
-    )?;
+    let returned_co_rec = execute_call("recursive", "echo_co_rec", || {
+        client.echo_co_rec(co_rec.clone())
+    })?;
     if returned_co_rec != co_rec {
-        return Err(format!("mismatched co_rec {:?} {:?}", co_rec, returned_co_rec).into(),);
+        return Err(format!("mismatched co_rec {:?} {:?}", co_rec, returned_co_rec).into());
     }
 
     Ok(())
@@ -266,14 +229,10 @@
 
     match res {
         Ok(_) => println!("{}: completed {} call", service_type, call_name),
-        Err(ref e) => {
-            println!(
-                "{}: failed {} call with error {:?}",
-                service_type,
-                call_name,
-                e
-            )
-        }
+        Err(ref e) => println!(
+            "{}: failed {} call with error {:?}",
+            service_type, call_name, e
+        ),
     }
 
     res
diff --git a/lib/rs/test/src/bin/kitchen_sink_server.rs b/lib/rs/test/src/bin/kitchen_sink_server.rs
index 15ceb29..73801ea 100644
--- a/lib/rs/test/src/bin/kitchen_sink_server.rs
+++ b/lib/rs/test/src/bin/kitchen_sink_server.rs
@@ -17,23 +17,32 @@
 
 #[macro_use]
 extern crate clap;
-
 extern crate kitchen_sink;
 extern crate thrift;
 
-use kitchen_sink::base_one::Noodle;
-use kitchen_sink::base_two::{Napkin, NapkinServiceSyncHandler, Ramen, RamenServiceSyncHandler};
-use kitchen_sink::midlayer::{Dessert, Meal, MealServiceSyncHandler, MealServiceSyncProcessor};
-use kitchen_sink::recursive;
-use kitchen_sink::ultimate::{Drink, FullMeal, FullMealAndDrinks,
-                             FullMealAndDrinksServiceSyncProcessor, FullMealServiceSyncHandler};
-use kitchen_sink::ultimate::FullMealAndDrinksServiceSyncHandler;
-use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory,
-                       TCompactInputProtocolFactory, TCompactOutputProtocolFactory,
-                       TInputProtocolFactory, TOutputProtocolFactory};
-use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory,
-                        TReadTransportFactory, TWriteTransportFactory};
+use thrift::protocol::{
+    TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory,
+    TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory,
+};
 use thrift::server::TServer;
+use thrift::transport::{
+    TFramedReadTransportFactory, TFramedWriteTransportFactory, TReadTransportFactory,
+    TWriteTransportFactory,
+};
+
+use kitchen_sink::base_one::Noodle;
+use kitchen_sink::base_two::{
+    BrothType, Napkin, NapkinServiceSyncHandler, Ramen, RamenServiceSyncHandler,
+};
+use kitchen_sink::midlayer::{
+    Dessert, Meal, MealServiceSyncHandler, MealServiceSyncProcessor, Pie,
+};
+use kitchen_sink::recursive;
+use kitchen_sink::ultimate::FullMealAndDrinksServiceSyncHandler;
+use kitchen_sink::ultimate::{
+    Drink, FullMeal, FullMealAndDrinks, FullMealAndDrinksServiceSyncProcessor,
+    FullMealServiceSyncHandler,
+};
 
 fn main() {
     match run() {
@@ -46,7 +55,6 @@
 }
 
 fn run() -> thrift::Result<()> {
-
     let matches = clap_app!(rust_kitchen_sink_server =>
         (version: "0.1.0")
         (author: "Apache Thrift Developers <dev@thrift.apache.org>")
@@ -67,21 +75,22 @@
     let r_transport_factory = TFramedReadTransportFactory::new();
     let w_transport_factory = TFramedWriteTransportFactory::new();
 
-    let (i_protocol_factory, o_protocol_factory): (Box<TInputProtocolFactory>,
-                                                   Box<TOutputProtocolFactory>) =
-        match &*protocol {
-            "binary" => {
-                (Box::new(TBinaryInputProtocolFactory::new()),
-                 Box::new(TBinaryOutputProtocolFactory::new()))
-            }
-            "compact" => {
-                (Box::new(TCompactInputProtocolFactory::new()),
-                 Box::new(TCompactOutputProtocolFactory::new()))
-            }
-            unknown => {
-                return Err(format!("unsupported transport type {}", unknown).into());
-            }
-        };
+    let (i_protocol_factory, o_protocol_factory): (
+        Box<TInputProtocolFactory>,
+        Box<TOutputProtocolFactory>,
+    ) = match &*protocol {
+        "binary" => (
+            Box::new(TBinaryInputProtocolFactory::new()),
+            Box::new(TBinaryOutputProtocolFactory::new()),
+        ),
+        "compact" => (
+            Box::new(TCompactInputProtocolFactory::new()),
+            Box::new(TCompactOutputProtocolFactory::new()),
+        ),
+        unknown => {
+            return Err(format!("unsupported transport type {}", unknown).into());
+        }
+    };
 
     // FIXME: should processor be boxed as well?
     //
@@ -94,33 +103,27 @@
     //
     // Since what I'm doing is uncommon I'm just going to duplicate the code
     match &*service {
-        "part" => {
-            run_meal_server(
-                &listen_address,
-                r_transport_factory,
-                i_protocol_factory,
-                w_transport_factory,
-                o_protocol_factory,
-            )
-        }
-        "full" => {
-            run_full_meal_server(
-                &listen_address,
-                r_transport_factory,
-                i_protocol_factory,
-                w_transport_factory,
-                o_protocol_factory,
-            )
-        }
-        "recursive" => {
-            run_recursive_server(
-                &listen_address,
-                r_transport_factory,
-                i_protocol_factory,
-                w_transport_factory,
-                o_protocol_factory,
-            )
-        }
+        "part" => run_meal_server(
+            &listen_address,
+            r_transport_factory,
+            i_protocol_factory,
+            w_transport_factory,
+            o_protocol_factory,
+        ),
+        "full" => run_full_meal_server(
+            &listen_address,
+            r_transport_factory,
+            i_protocol_factory,
+            w_transport_factory,
+            o_protocol_factory,
+        ),
+        "recursive" => run_recursive_server(
+            &listen_address,
+            r_transport_factory,
+            i_protocol_factory,
+            w_transport_factory,
+            o_protocol_factory,
+        ),
         unknown => Err(format!("unsupported service type {}", unknown).into()),
     }
 }
@@ -207,7 +210,13 @@
 
 impl FullMealAndDrinksServiceSyncHandler for FullHandler {
     fn handle_full_meal_and_drinks(&self) -> thrift::Result<FullMealAndDrinks> {
-        Ok(FullMealAndDrinks::new(full_meal(), Drink::WHISKEY))
+        println!("full_meal_and_drinks: handling full meal and drinks call");
+        Ok(FullMealAndDrinks::new(full_meal(), Drink::CanadianWhisky))
+    }
+
+    fn handle_best_pie(&self) -> thrift::Result<Pie> {
+        println!("full_meal_and_drinks: handling pie call");
+        Ok(Pie::MississippiMud) // I prefer Pie::Pumpkin, but I have to check that casing works
     }
 }
 
@@ -252,7 +261,7 @@
 }
 
 fn ramen() -> Ramen {
-    Ramen::new("Mr Ramen".to_owned(), 72)
+    Ramen::new("Mr Ramen".to_owned(), 72, BrothType::Miso)
 }
 
 fn napkin() -> Napkin {
diff --git a/lib/rs/test/thrifts/Base_One.thrift b/lib/rs/test/thrifts/Base_One.thrift
index 3da083d..c5fa6c2 100644
--- a/lib/rs/test/thrifts/Base_One.thrift
+++ b/lib/rs/test/thrifts/Base_One.thrift
@@ -37,6 +37,9 @@
 
 const double MealsPerDay = 2.5;
 
+const string DefaultRecipeName = "Soup-rise of the Day"
+const binary DefaultRecipeBinary = "Soup-rise of the 01010101"
+
 struct Noodle {
   1: string flourType
   2: Temperature cookTemp
diff --git a/lib/rs/test/thrifts/Base_Two.thrift b/lib/rs/test/thrifts/Base_Two.thrift
index b4b4ea1..caa6acb 100644
--- a/lib/rs/test/thrifts/Base_Two.thrift
+++ b/lib/rs/test/thrifts/Base_Two.thrift
@@ -23,9 +23,15 @@
 
 const i32 WaterWeight = 200
 
+enum brothType {
+  Miso,
+  shouyu,
+}
+
 struct Ramen {
   1: optional string ramenType
   2: required i32 noodleCount
+  3: brothType broth
 }
 
 struct Napkin {
diff --git a/lib/rs/test/thrifts/Midlayer.thrift b/lib/rs/test/thrifts/Midlayer.thrift
index cf1157c..16ff49b 100644
--- a/lib/rs/test/thrifts/Midlayer.thrift
+++ b/lib/rs/test/thrifts/Midlayer.thrift
@@ -46,6 +46,15 @@
   [6, 7, 8]
 ]
 
+enum Pie {
+  PUMPKIN,
+  apple, // intentionally poorly cased
+  STRAWBERRY_RHUBARB,
+  Key_Lime, // intentionally poorly cased
+  coconut_Cream, // intentionally poorly cased
+  mississippi_mud, // intentionally poorly cased
+}
+
 struct Meal {
   1: Base_One.Noodle noodle
   2: Base_Two.Ramen ramen
diff --git a/lib/rs/test/thrifts/Ultimate.thrift b/lib/rs/test/thrifts/Ultimate.thrift
index 8154d91..72fa100 100644
--- a/lib/rs/test/thrifts/Ultimate.thrift
+++ b/lib/rs/test/thrifts/Ultimate.thrift
@@ -27,6 +27,21 @@
   WATER,
   WHISKEY,
   WINE,
+  scotch, // intentionally poorly cased
+  LATE_HARVEST_WINE,
+  India_Pale_Ale, // intentionally poorly cased
+  apple_cider, // intentially poorly cased
+  belgian_Ale, // intentionally poorly cased
+  Canadian_whisky, // intentionally poorly cased
+}
+
+const map<i8, Midlayer.Pie> RankedPies = {
+  1: Midlayer.Pie.PUMPKIN,
+  2: Midlayer.Pie.STRAWBERRY_RHUBARB,
+  3: Midlayer.Pie.apple,
+  4: Midlayer.Pie.mississippi_mud,
+  5: Midlayer.Pie.coconut_Cream,
+  6: Midlayer.Pie.Key_Lime,
 }
 
 struct FullMeal {
@@ -45,5 +60,7 @@
 
 service FullMealAndDrinksService extends FullMealService {
   FullMealAndDrinks fullMealAndDrinks()
+
+  Midlayer.Pie bestPie()
 }
 
diff --git a/lib/st/package.xml b/lib/st/package.xml
index 5044e2a..f83936a 100644
--- a/lib/st/package.xml
+++ b/lib/st/package.xml
@@ -17,7 +17,7 @@
  specific language governing permissions and limitations
  under the License.
  -->
-<!-- Apache Thrift Smalltalk library version 0.11.0 -->
+<!-- Apache Thrift Smalltalk library version 1.0.0 -->
 <package>
   <name>libthrift-st</name>
   <file>thrift.st</file>
diff --git a/lib/swift/Makefile.am b/lib/swift/Makefile.am
new file mode 100644
index 0000000..6b88b06
--- /dev/null
+++ b/lib/swift/Makefile.am
@@ -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.
+#
+
+SUBDIRS = .
+
+all-local:
+	swift build --configuration release
+
+install-exec-hook:
+	swift install
+
+clean-local:
+	swift package clean
+	rm -rf .build
+
+precross:
+	swift
+
+check-local:
+	swift test
+
+EXTRA_DIST = \
+	Package.swift \
+	Sources \
+	Tests \
+	README.md
+
+MAINTAINERCLEANFILES = \
+	Makefile \
+	Makefile.in
diff --git a/test/php/TestPsr4.php b/lib/swift/Package.swift
similarity index 91%
copy from test/php/TestPsr4.php
copy to lib/swift/Package.swift
index d30bf1c..b533f60 100644
--- a/test/php/TestPsr4.php
+++ b/lib/swift/Package.swift
@@ -17,7 +17,8 @@
  * under the License.
  */
 
-<?php
-$GEN_DIR = 'gen-php-psr4';
-include_once('TestClient.php');
-?>
+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..6f10961
--- /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. |
+| safe_enums     | Generate enum types with an unknown case to handle unspecified values rather than throw a serialization error  |
+
+
+
+*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 validate fields.  The `no_strict` option here will ignore the validation check, as well as behave similar to the Swift2/Cocoa generator and initialize required fields with empty initializers (where possible).
+
+
+## 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/go/thrift/common_test_pre_go17.go b/lib/swift/Sources/TBinary.swift
similarity index 72%
rename from lib/go/thrift/common_test_pre_go17.go
rename to lib/swift/Sources/TBinary.swift
index e6d0c4d..4be5644 100644
--- a/lib/go/thrift/common_test_pre_go17.go
+++ b/lib/swift/Sources/TBinary.swift
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,14 +17,16 @@
  * under the License.
  */
 
-package thrift
+import Foundation
 
-import "golang.org/x/net/context"
-
-type mockProcessor struct {
-	ProcessFunc func(in, out TProtocol) (bool, TException)
-}
-
-func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	return m.ProcessFunc(in, out)
+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..a97249a
--- /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 Double(bitPattern: UInt64(bitPattern: val))
+  }
+  
+  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(Int64(bitPattern: value.bitPattern))
+  }
+  
+  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..cc3288a
--- /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
+
+  required public init(inoutProtocol: TProtocol) {
+    self.inProtocol = inoutProtocol
+    self.outProtocol = inoutProtocol
+  }
+
+  required 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..59773c3
--- /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(bitPattern: Int32(n << 1) ^ Int32(n >> 31))
+  }
+
+  func i64ToZigZag(_ n : Int64) -> UInt64 {
+    return UInt64(bitPattern: Int64(n << 1) ^ Int64(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 Double(bitPattern: bits)
+  }
+  
+  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(value.bitPattern)
+    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/go/thrift/common_test_pre_go17.go b/lib/swift/Sources/TEnum.swift
similarity index 72%
copy from lib/go/thrift/common_test_pre_go17.go
copy to lib/swift/Sources/TEnum.swift
index e6d0c4d..fedfdb1 100644
--- a/lib/go/thrift/common_test_pre_go17.go
+++ b/lib/swift/Sources/TEnum.swift
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -19,14 +17,16 @@
  * under the License.
  */
 
-package thrift
 
-import "golang.org/x/net/context"
-
-type mockProcessor struct {
-	ProcessFunc func(in, out TProtocol) (bool, TException)
+public protocol TEnum : TSerializable, Hashable {
+  var rawValue: Int32 { get }
 }
 
-func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
-	return m.ProcessFunc(in, out)
+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..c239d10
--- /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 {
+  public 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..8980377
--- /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 {
+  public 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..1ecd170
--- /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
+  public 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..0316e37
--- /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 as CFString)
+            CFWriteStreamSetProperty(writeStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL.rawValue as CFString)
+        }
+
+      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..5bd1758
--- /dev/null
+++ b/lib/swift/Sources/Thrift.swift
@@ -0,0 +1,3 @@
+class Thrift {
+	let version = "1.1.0"
+}
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..56a5572
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift
@@ -0,0 +1,168 @@
+//
+//  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)")
+    }
+  }
+  func testUnsafeBitcastUpdate() {
+    let value: Double = 3.14159
+    let val: Int64 = 31415926
+    let uval: UInt64 = 31415926
+    
+    let i64 = Int64(bitPattern: value.bitPattern)
+    let ubc = unsafeBitCast(value, to: Int64.self)
+    
+    XCTAssertEqual(i64, ubc, "Bitcast Double-> i64 Values don't match")
+    
+    let dbl = Double(bitPattern: UInt64(val))
+    let ubdb = unsafeBitCast(val, to: Double.self)
+    
+    XCTAssertEqual(dbl, ubdb, "Bitcast i64 -> Double Values don't match")
+    
+    let db2 = Double(bitPattern: uval)
+    let usbc2 = unsafeBitCast(uval, to: Double.self)
+    
+    XCTAssertEqual(db2, usbc2, "Bitcast u64 -> Double Values don't match")
+
+    
+  }
+  
+  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..882c260
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/TCompactProtocolTests.swift
@@ -0,0 +1,210 @@
+//
+//  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)")
+    }
+  }
+  
+  func testInt32ZigZag() {
+    let zero: Int32 = 0
+    let one: Int32 = 1
+    let nOne: Int32 = -1
+    let two: Int32 = 2
+    let nTwo: Int32 = -2
+    let max = Int32.max
+    let min = Int32.min
+
+    XCTAssertEqual(proto.i32ToZigZag(zero), UInt32(0), "Error 32bit zigzag on \(zero)")
+    XCTAssertEqual(proto.zigZagToi32(0), zero, "Error 32bit zigzag on \(zero)")
+
+    XCTAssertEqual(proto.i32ToZigZag(nOne), UInt32(1), "Error 32bit zigzag on \(nOne)")
+    XCTAssertEqual(proto.zigZagToi32(1), nOne, "Error 32bit zigzag on \(nOne)")
+
+    XCTAssertEqual(proto.i32ToZigZag(one), UInt32(2), "Error 32bit zigzag on \(one)")
+    XCTAssertEqual(proto.zigZagToi32(2), one, "Error 32bit zigzag on \(one)")
+
+    XCTAssertEqual(proto.i32ToZigZag(nTwo), UInt32(3), "Error 32bit zigzag on \(nTwo)")
+    XCTAssertEqual(proto.zigZagToi32(3), nTwo, "Error 32bit zigzag on \(nTwo)")
+
+    XCTAssertEqual(proto.i32ToZigZag(two), UInt32(4), "Error 32bit zigzag on \(two)")
+    XCTAssertEqual(proto.zigZagToi32(4), two, "Error 32bit zigzag on \(two)")
+
+    let uMaxMinusOne: UInt32 = UInt32.max - 1
+    XCTAssertEqual(proto.i32ToZigZag(max), uMaxMinusOne, "Error 32bit zigzag on \(max)")
+    XCTAssertEqual(proto.zigZagToi32(uMaxMinusOne), max, "Error 32bit zigzag on \(max)")
+
+    XCTAssertEqual(proto.i32ToZigZag(min), UInt32.max, "Error 32bit zigzag on \(min)")
+    XCTAssertEqual(proto.zigZagToi32(UInt32.max), min, "Error 32bit zigzag on \(min)")
+  }
+
+  func testInt64ZigZag() {
+    let zero: Int64 = 0
+    let one: Int64 = 1
+    let nOne: Int64 = -1
+    let two: Int64 = 2
+    let nTwo: Int64 = -2
+    let max = Int64.max
+    let min = Int64.min
+
+    XCTAssertEqual(proto.i64ToZigZag(zero), UInt64(0), "Error 64bit zigzag on \(zero)")
+    XCTAssertEqual(proto.zigZagToi64(0), zero, "Error 64bit zigzag on \(zero)")
+
+    XCTAssertEqual(proto.i64ToZigZag(nOne), UInt64(1), "Error 64bit zigzag on \(nOne)")
+    XCTAssertEqual(proto.zigZagToi64(1), nOne, "Error 64bit zigzag on \(nOne)")
+
+    XCTAssertEqual(proto.i64ToZigZag(one), UInt64(2), "Error 64bit zigzag on \(one)")
+    XCTAssertEqual(proto.zigZagToi64(2), one, "Error 64bit zigzag on \(one)")
+
+    XCTAssertEqual(proto.i64ToZigZag(nTwo), UInt64(3), "Error 64bit zigzag on \(nTwo)")
+    XCTAssertEqual(proto.zigZagToi64(3), nTwo, "Error 64bit zigzag on \(nTwo)")
+
+    XCTAssertEqual(proto.i64ToZigZag(two), UInt64(4), "Error 64bit zigzag on \(two)")
+    XCTAssertEqual(proto.zigZagToi64(4), two, "Error 64bit zigzag on \(two)")
+
+    let uMaxMinusOne: UInt64 = UInt64.max - 1
+    XCTAssertEqual(proto.i64ToZigZag(max), uMaxMinusOne, "Error 64bit zigzag on \(max)")
+    XCTAssertEqual(proto.zigZagToi64(uMaxMinusOne), max, "Error 64bit zigzag on \(max)")
+
+    XCTAssertEqual(proto.i64ToZigZag(min), UInt64.max, "Error 64bit zigzag on \(min)")
+    XCTAssertEqual(proto.zigZagToi64(UInt64.max), min, "Error 64bit zigzag on \(min)")
+  }
+  
+  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),
+      ("testInt32ZigZag", testInt32ZigZag),
+      ("testInt64ZigZag", testInt64ZigZag)
+    ]
+  }
+}
diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift
new file mode 100644
index 0000000..9316100
--- /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, "1.1.0")
+  }
+
+  func test_in_addr_extension() {
+
+  }
+
+  static var allTests : [(String, (ThriftTests) -> () throws -> Void)] {
+    return [
+      ("testVersion", testVersion),
+    ]
+  }
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..b265aa6
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2183 @@
+{
+  "name": "thrift",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.0.0"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      }
+    },
+    "@types/node": {
+      "version": "10.12.6",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.6.tgz",
+      "integrity": "sha512-+ZWB5Ec1iki99xQFzBlivlKxSZQ+fuUKBott8StBOnLN4dWbRHlgdg1XknpW6g0tweniN5DcOqA64CJyOUPSAw==",
+      "dev": true
+    },
+    "@types/q": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz",
+      "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==",
+      "dev": true
+    },
+    "abbrev": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+      "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
+      "dev": true
+    },
+    "acorn": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz",
+      "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==",
+      "dev": true
+    },
+    "acorn-jsx": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.0.tgz",
+      "integrity": "sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg==",
+      "dev": true
+    },
+    "ajv": {
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+      "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true,
+      "optional": true
+    },
+    "ansi-escapes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
+      "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "dev": true
+    },
+    "are-we-there-yet": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+      "dev": true,
+      "requires": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^2.0.6"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "dev": true,
+      "requires": {
+        "array-uniq": "^1.0.1"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+      "dev": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "dev": true
+    },
+    "async": {
+      "version": "1.5.2",
+      "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
+    },
+    "async-limiter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+    },
+    "babylon": {
+      "version": "7.0.0-beta.19",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
+      "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "bindings": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
+      "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==",
+      "dev": true
+    },
+    "bl": {
+      "version": "1.2.2",
+      "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+      "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^2.3.5",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "bluebird": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
+      "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "buffer-alloc": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "dev": true,
+      "requires": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+      "dev": true
+    },
+    "buffer-equals": {
+      "version": "1.0.4",
+      "resolved": "http://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz",
+      "integrity": "sha1-A1O1T9B/2VZBcGca5vZrnPENJ/U=",
+      "dev": true
+    },
+    "buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+      "dev": true
+    },
+    "caller-path": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+      "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+      "dev": true,
+      "requires": {
+        "callsites": "^0.2.0"
+      }
+    },
+    "callsites": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+      "dev": true
+    },
+    "catharsis": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
+      "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
+      "dev": true,
+      "requires": {
+        "underscore-contrib": "~0.3.0"
+      }
+    },
+    "chalk": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+      "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+      "dev": true
+    },
+    "chownr": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+      "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
+      "dev": true
+    },
+    "circular-json": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+      "dev": true
+    },
+    "cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^2.0.0"
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+      "dev": true
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "commander": {
+      "version": "2.19.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+      "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "connect": {
+      "version": "3.6.6",
+      "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
+      "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "finalhandler": "1.1.0",
+        "parseurl": "~1.3.2",
+        "utils-merge": "1.0.1"
+      }
+    },
+    "console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "decompress-response": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+      "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+      "dev": true,
+      "requires": {
+        "mimic-response": "^1.0.0"
+      }
+    },
+    "deep-equal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+      "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+      "dev": true
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "dev": true
+    },
+    "define-properties": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+      "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+      "dev": true,
+      "requires": {
+        "object-keys": "^1.0.12"
+      }
+    },
+    "defined": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+      "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+      "dev": true
+    },
+    "del": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+      "dev": true,
+      "requires": {
+        "globby": "^5.0.0",
+        "is-path-cwd": "^1.0.0",
+        "is-path-in-cwd": "^1.0.0",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "rimraf": "^2.2.8"
+      }
+    },
+    "delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+      "dev": true
+    },
+    "detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
+      "dev": true
+    },
+    "doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2"
+      }
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+      "dev": true
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+      "dev": true
+    },
+    "end-of-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "es-abstract": {
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
+      "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "^1.1.1",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.1",
+        "is-callable": "^1.1.3",
+        "is-regex": "^1.0.4"
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+      "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      }
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "escodegen": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+      "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+      "dev": true,
+      "requires": {
+        "esprima": "^2.7.1",
+        "estraverse": "^1.9.1",
+        "esutils": "^2.0.2",
+        "optionator": "^0.8.1",
+        "source-map": "~0.2.0"
+      },
+      "dependencies": {
+        "esprima": {
+          "version": "2.7.3",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+          "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+          "dev": true
+        },
+        "estraverse": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+          "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
+          "dev": true
+        }
+      }
+    },
+    "eslint": {
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz",
+      "integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "ajv": "^6.5.3",
+        "chalk": "^2.1.0",
+        "cross-spawn": "^6.0.5",
+        "debug": "^4.0.1",
+        "doctrine": "^2.1.0",
+        "eslint-scope": "^4.0.0",
+        "eslint-utils": "^1.3.1",
+        "eslint-visitor-keys": "^1.0.0",
+        "espree": "^4.0.0",
+        "esquery": "^1.0.1",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^2.0.0",
+        "functional-red-black-tree": "^1.0.1",
+        "glob": "^7.1.2",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.6",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^6.1.0",
+        "is-resolvable": "^1.1.0",
+        "js-yaml": "^3.12.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.5",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.2",
+        "path-is-inside": "^1.0.2",
+        "pluralize": "^7.0.0",
+        "progress": "^2.0.0",
+        "regexpp": "^2.0.1",
+        "require-uncached": "^1.0.3",
+        "semver": "^5.5.1",
+        "strip-ansi": "^4.0.0",
+        "strip-json-comments": "^2.0.1",
+        "table": "^5.0.2",
+        "text-table": "^0.2.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+          "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        }
+      }
+    },
+    "eslint-config-prettier": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz",
+      "integrity": "sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^6.0.0"
+      }
+    },
+    "eslint-plugin-prettier": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz",
+      "integrity": "sha512-4g11opzhqq/8+AMmo5Vc2Gn7z9alZ4JqrbZ+D4i8KlSyxeQhZHlmIrY8U9Akf514MoEhogPa87Jgkq87aZ2Ohw==",
+      "dev": true,
+      "requires": {
+        "prettier-linter-helpers": "^1.0.0"
+      }
+    },
+    "eslint-scope": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+      "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "eslint-utils": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
+      "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
+      "dev": true
+    },
+    "eslint-visitor-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+      "dev": true
+    },
+    "espree": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
+      "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
+      "dev": true,
+      "requires": {
+        "acorn": "^6.0.2",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
+      }
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
+    "esquery": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+      "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.0.0"
+      }
+    },
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "dev": true
+    },
+    "expand-template": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
+      "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==",
+      "dev": true
+    },
+    "external-editor": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
+      "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
+      "dev": true,
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+      "dev": true
+    },
+    "fast-diff": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+      "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+      "dev": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+      "dev": true
+    },
+    "figures": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "file-entry-cache": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+      "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+      "dev": true,
+      "requires": {
+        "flat-cache": "^1.2.1",
+        "object-assign": "^4.0.1"
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+      "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.1",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.2",
+        "statuses": "~1.3.1",
+        "unpipe": "~1.0.0"
+      }
+    },
+    "flat-cache": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "dev": true,
+      "requires": {
+        "circular-json": "^0.3.1",
+        "del": "^2.0.2",
+        "graceful-fs": "^4.1.2",
+        "write": "^0.2.1"
+      }
+    },
+    "for-each": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.3"
+      }
+    },
+    "fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+      "dev": true
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "functional-red-black-tree": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+      "dev": true
+    },
+    "gauge": {
+      "version": "2.7.4",
+      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.0.3",
+        "console-control-strings": "^1.0.0",
+        "has-unicode": "^2.0.0",
+        "object-assign": "^4.1.0",
+        "signal-exit": "^3.0.0",
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wide-align": "^1.1.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "get-stdin": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
+      "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
+      "dev": true
+    },
+    "github-from-package": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+      "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
+      "dev": true
+    },
+    "glob": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "globals": {
+      "version": "11.8.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz",
+      "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==",
+      "dev": true
+    },
+    "globby": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+      "dev": true,
+      "requires": {
+        "array-union": "^1.0.1",
+        "arrify": "^1.0.0",
+        "glob": "^7.0.3",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "dev": true
+    },
+    "handlebars": {
+      "version": "4.0.12",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz",
+      "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==",
+      "dev": true,
+      "requires": {
+        "async": "^2.5.0",
+        "optimist": "^0.6.1",
+        "source-map": "^0.6.1",
+        "uglify-js": "^3.1.4"
+      },
+      "dependencies": {
+        "async": {
+          "version": "2.6.1",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
+          "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
+          "dev": true,
+          "requires": {
+            "lodash": "^4.17.10"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "has-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+      "dev": true
+    },
+    "has-unicode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+      "dev": true
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "ignore": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+      "dev": true
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "inquirer": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
+      "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^3.0.0",
+        "chalk": "^2.0.0",
+        "cli-cursor": "^2.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.0",
+        "figures": "^2.0.0",
+        "lodash": "^4.17.10",
+        "mute-stream": "0.0.7",
+        "run-async": "^2.2.0",
+        "rxjs": "^6.1.0",
+        "string-width": "^2.1.0",
+        "strip-ansi": "^4.0.0",
+        "through": "^2.3.6"
+      }
+    },
+    "is-callable": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+      "dev": true
+    },
+    "is-date-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "dev": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "dev": true
+    },
+    "is-path-cwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+      "dev": true
+    },
+    "is-path-in-cwd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+      "dev": true,
+      "requires": {
+        "is-path-inside": "^1.0.0"
+      }
+    },
+    "is-path-inside": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+      "dev": true,
+      "requires": {
+        "path-is-inside": "^1.0.1"
+      }
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-regex": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.1"
+      }
+    },
+    "is-resolvable": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
+      "dev": true
+    },
+    "is-symbol": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+      "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.0"
+      }
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "istanbul": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+      "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1.0.x",
+        "async": "1.x",
+        "escodegen": "1.8.x",
+        "esprima": "2.7.x",
+        "glob": "^5.0.15",
+        "handlebars": "^4.0.1",
+        "js-yaml": "3.x",
+        "mkdirp": "0.5.x",
+        "nopt": "3.x",
+        "once": "1.x",
+        "resolve": "1.1.x",
+        "supports-color": "^3.1.0",
+        "which": "^1.1.1",
+        "wordwrap": "^1.0.0"
+      },
+      "dependencies": {
+        "esprima": {
+          "version": "2.7.3",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+          "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+          "dev": true
+        },
+        "glob": {
+          "version": "5.0.15",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+          "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+          "dev": true,
+          "requires": {
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "2 || 3",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "has-flag": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "3.2.3",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+          "dev": true,
+          "requires": {
+            "has-flag": "^1.0.0"
+          }
+        }
+      }
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
+      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "js2xmlparser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
+      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
+      "dev": true,
+      "requires": {
+        "xmlcreate": "^1.0.1"
+      }
+    },
+    "jsdoc": {
+      "version": "3.5.5",
+      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
+      "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
+      "dev": true,
+      "requires": {
+        "babylon": "7.0.0-beta.19",
+        "bluebird": "~3.5.0",
+        "catharsis": "~0.8.9",
+        "escape-string-regexp": "~1.0.5",
+        "js2xmlparser": "~3.0.0",
+        "klaw": "~2.0.0",
+        "marked": "~0.3.6",
+        "mkdirp": "~0.5.1",
+        "requizzle": "~0.2.1",
+        "strip-json-comments": "~2.0.1",
+        "taffydb": "2.6.2",
+        "underscore": "~1.8.3"
+      }
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+      "dev": true
+    },
+    "klaw": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
+      "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.9"
+      }
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
+      }
+    },
+    "lodash": {
+      "version": "4.17.11",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "dev": true
+    },
+    "marked": {
+      "version": "0.3.19",
+      "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
+      "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
+      "dev": true
+    },
+    "mimic-fn": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+      "dev": true
+    },
+    "mimic-response": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+      "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "mute-stream": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+      "dev": true
+    },
+    "nan": {
+      "version": "2.10.0",
+      "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
+      "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
+      "dev": true
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "node-abi": {
+      "version": "2.4.5",
+      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.5.tgz",
+      "integrity": "sha512-aa/UC6Nr3+tqhHGRsAuw/edz7/q9nnetBrKWxj6rpTtm+0X9T1qU7lIEHMS3yN9JwAbRiKUbRRFy1PLz/y3aaA==",
+      "dev": true,
+      "requires": {
+        "semver": "^5.4.1"
+      }
+    },
+    "node-int64": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+      "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs="
+    },
+    "noop-logger": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
+      "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
+      "dev": true
+    },
+    "nopt": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1"
+      }
+    },
+    "npmlog": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+      "dev": true,
+      "requires": {
+        "are-we-there-yet": "~1.1.2",
+        "console-control-strings": "~1.1.0",
+        "gauge": "~2.7.3",
+        "set-blocking": "~2.0.0"
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-inspect": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
+      "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+      "dev": true
+    },
+    "object-keys": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+      "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
+      "dev": true
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "dev": true,
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^1.0.0"
+      }
+    },
+    "optimist": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+      "dev": true,
+      "requires": {
+        "minimist": "~0.0.1",
+        "wordwrap": "~0.0.2"
+      },
+      "dependencies": {
+        "wordwrap": {
+          "version": "0.0.3",
+          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+          "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+          "dev": true
+        }
+      }
+    },
+    "optionator": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "dev": true,
+      "requires": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "parseurl": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+      "dev": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "pluralize": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+      "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
+      "dev": true
+    },
+    "prebuild-install": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz",
+      "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==",
+      "dev": true,
+      "requires": {
+        "detect-libc": "^1.0.3",
+        "expand-template": "^1.0.2",
+        "github-from-package": "0.0.0",
+        "minimist": "^1.2.0",
+        "mkdirp": "^0.5.1",
+        "node-abi": "^2.2.0",
+        "noop-logger": "^0.1.1",
+        "npmlog": "^4.0.1",
+        "os-homedir": "^1.0.1",
+        "pump": "^2.0.1",
+        "rc": "^1.1.6",
+        "simple-get": "^2.7.0",
+        "tar-fs": "^1.13.0",
+        "tunnel-agent": "^0.6.0",
+        "which-pm-runs": "^1.0.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+      "dev": true
+    },
+    "prettier": {
+      "version": "1.14.3",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz",
+      "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==",
+      "dev": true
+    },
+    "prettier-linter-helpers": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+      "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+      "dev": true,
+      "requires": {
+        "fast-diff": "^1.1.2"
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+      "dev": true
+    },
+    "progress": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz",
+      "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==",
+      "dev": true
+    },
+    "pump": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "dev": true
+    },
+    "q": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+      "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+    },
+    "rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.6",
+      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "regexpp": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "dev": true
+    },
+    "require-uncached": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+      "dev": true,
+      "requires": {
+        "caller-path": "^0.1.0",
+        "resolve-from": "^1.0.0"
+      }
+    },
+    "requizzle": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
+      "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
+      "dev": true,
+      "requires": {
+        "underscore": "~1.6.0"
+      },
+      "dependencies": {
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+          "dev": true
+        }
+      }
+    },
+    "resolve": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+      "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+      "dev": true
+    },
+    "resolve-from": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+      "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+      "dev": true,
+      "requires": {
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "resumer": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
+      "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
+      "dev": true,
+      "requires": {
+        "through": "~2.3.4"
+      }
+    },
+    "rimraf": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.5"
+      }
+    },
+    "run-async": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "dev": true,
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
+    },
+    "rxjs": {
+      "version": "6.3.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+      "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+      "dev": true
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "simple-concat": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
+      "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=",
+      "dev": true
+    },
+    "simple-get": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
+      "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
+      "dev": true,
+      "requires": {
+        "decompress-response": "^3.3.0",
+        "once": "^1.3.1",
+        "simple-concat": "^1.0.0"
+      }
+    },
+    "slice-ansi": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "dev": true,
+      "requires": {
+        "is-fullwidth-code-point": "^2.0.0"
+      }
+    },
+    "source-map": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+      "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "amdefine": ">=0.0.4"
+      }
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "statuses": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+      "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+      "dev": true
+    },
+    "string-width": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "dev": true,
+      "requires": {
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^4.0.0"
+      }
+    },
+    "string.prototype.trim": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
+      "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.5.0",
+        "function-bind": "^1.0.2"
+      }
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^3.0.0"
+      }
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "dev": true
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "table": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
+      "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.5.3",
+        "lodash": "^4.17.10",
+        "slice-ansi": "1.0.0",
+        "string-width": "^2.1.1"
+      }
+    },
+    "taffydb": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
+      "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
+      "dev": true
+    },
+    "tape": {
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
+      "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==",
+      "dev": true,
+      "requires": {
+        "deep-equal": "~1.0.1",
+        "defined": "~1.0.0",
+        "for-each": "~0.3.3",
+        "function-bind": "~1.1.1",
+        "glob": "~7.1.2",
+        "has": "~1.0.3",
+        "inherits": "~2.0.3",
+        "minimist": "~1.2.0",
+        "object-inspect": "~1.6.0",
+        "resolve": "~1.7.1",
+        "resumer": "~0.0.0",
+        "string.prototype.trim": "~1.1.2",
+        "through": "~2.3.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.7.1",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
+          "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.5"
+          }
+        }
+      }
+    },
+    "tar-fs": {
+      "version": "1.16.3",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
+      "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
+      "dev": true,
+      "requires": {
+        "chownr": "^1.0.1",
+        "mkdirp": "^0.5.1",
+        "pump": "^1.0.0",
+        "tar-stream": "^1.1.2"
+      },
+      "dependencies": {
+        "pump": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
+          "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        }
+      }
+    },
+    "tar-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+      "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+      "dev": true,
+      "requires": {
+        "bl": "^1.0.0",
+        "buffer-alloc": "^1.2.0",
+        "end-of-stream": "^1.0.0",
+        "fs-constants": "^1.0.0",
+        "readable-stream": "^2.3.0",
+        "to-buffer": "^1.1.1",
+        "xtend": "^4.0.0"
+      }
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+      "dev": true
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+      "dev": true
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "dev": true,
+      "requires": {
+        "os-tmpdir": "~1.0.2"
+      }
+    },
+    "to-buffer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+      "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
+      "dev": true
+    },
+    "tslib": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+      "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2"
+      }
+    },
+    "typescript": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz",
+      "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "3.4.9",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
+      "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "commander": "~2.17.1",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.17.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+          "dev": true,
+          "optional": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "underscore": {
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
+      "dev": true
+    },
+    "underscore-contrib": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
+      "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
+      "dev": true,
+      "requires": {
+        "underscore": "1.6.0"
+      },
+      "dependencies": {
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+          "dev": true
+        }
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+      "dev": true
+    },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "utf-8-validate": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-4.0.2.tgz",
+      "integrity": "sha512-CS63Ssp6zynBQ4IxVzgjP5Abdo6LuJ87HFIcgIiVUeY96+MTHkqKtrUhphbwQ6jX8aSGZv8zX6l1DCPpfcAnxA==",
+      "dev": true,
+      "requires": {
+        "bindings": "~1.3.0",
+        "nan": "~2.10.0",
+        "prebuild-install": "~4.0.0"
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "dev": true
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "which-pm-runs": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
+      "dev": true
+    },
+    "wide-align": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.2 || 2"
+      }
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+      "dev": true
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "write": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+      "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+      "dev": true,
+      "requires": {
+        "mkdirp": "^0.5.1"
+      }
+    },
+    "ws": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
+      "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+      "requires": {
+        "async-limiter": "~1.0.0"
+      }
+    },
+    "xmlcreate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
+      "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=",
+      "dev": true
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+      "dev": true
+    }
+  }
+}
diff --git a/package.json b/package.json
index 24851b2..99553ee 100644
--- a/package.json
+++ b/package.json
@@ -4,9 +4,9 @@
   "homepage": "http://thrift.apache.org/",
   "repository": {
     "type": "git",
-    "url": "https://git-wip-us.apache.org/repos/asf/thrift.git"
+    "url": "https://github.com/apache/thrift.git"
   },
-  "version": "0.11.0",
+  "version": "1.0.0",
   "author": {
     "name": "Apache Thrift Developers",
     "email": "dev@thrift.apache.org",
@@ -37,22 +37,30 @@
   "dependencies": {
     "node-int64": "^0.4.0",
     "q": "^1.5.0",
-    "ws": ">= 2.2.3"
+    "ws": "^5.0.0"
   },
   "devDependencies": {
     "buffer-equals": "^1.0.4",
-    "commander": "^2.11.0",
-    "connect": "^3.6.4",
+    "commander": "^2.14.1",
+    "connect": "^3.6.6",
+    "eslint": "^5.7.0",
+    "eslint-config-prettier": "^3.1.0",
+    "eslint-plugin-prettier": "^3.0.0",
     "istanbul": "^0.4.5",
-    "jsdoc": ">=3.5.5",
-    "minimatch": "^3.0.4",
-    "phantomjs-prebuilt": "^2.1.7",
-    "run-browser": "^2.0.2",
-    "tape": "^4.8.0",
-    "utf-8-validate": "^3.0.0"
+    "jsdoc": "^3.5.5",
+    "prettier": "^1.14.3",
+    "tape": "^4.9.0",
+    "utf-8-validate": "^4.0.0",
+    "typescript": "^3.1.6",
+    "@types/node": "^10.12.6",
+    "@types/q": "^1.5.1"
   },
   "scripts": {
     "cover": "lib/nodejs/test/testAll.sh COVER",
-    "test": "lib/nodejs/test/testAll.sh"
+    "test": "lib/nodejs/test/testAll.sh",
+    "test-ts": "lib/nodets/test/testAll.sh",
+    "prettier": "prettier --write '**/*.js'",
+    "lint": "eslint lib/nodejs/. --ext .js",
+    "lint-tests": "eslint lib/nodejs/test/. --ext .js"
   }
 }
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..180388a
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<ruleset name="Apache_Thrift">
+    <description>The coding standard for thrift.</description>
+
+    <file>lib/php/lib</file>
+    <file>lib/php/test</file>
+    <exclude-pattern>lib/php/test/packages/*</exclude-pattern>
+
+    <arg name="basepath" value="."/>
+    <arg name="colors" />
+    <arg name="parallel" value="4" />
+
+    <rule ref="PSR2">
+        <exclude name="PSR2.Methods.MethodDeclaration.Underscore"/>
+        <exclude name="PSR2.Classes.PropertyDeclaration.Underscore"/>
+    </rule>
+
+    <rule ref="PSR1.Files.SideEffects">
+        <exclude-pattern>lib/php/test/*</exclude-pattern>
+    </rule>
+    <rule ref="Generic.Files.LineLength">
+        <exclude-pattern>lib/php/test/*</exclude-pattern>
+    </rule>
+
+</ruleset>
diff --git a/pull_request_template.md b/pull_request_template.md
new file mode 100644
index 0000000..0b6965b
--- /dev/null
+++ b/pull_request_template.md
@@ -0,0 +1,19 @@
+Some helpful tips for a successful Apache Thrift PR:
+
+* Did you test your changes locally or using CI in your fork?
+* Is the Apache Jira THRIFT ticket identifier in the PR title?
+* Is the Apache Jira THRIFT ticket identifier in the commit message?
+* Did you squash your changes to a single commit?
+* Are these changes backwards compatible? (please say so in PR description)
+* Do you need to update the language-specific README?
+
+Example ideal pull request title:
+
+        THRIFT-9999: an example pull request title
+
+Example ideal commit message:
+
+        THRIFT-9999: [summary of fix, one line if possible]
+        Client: [language(s) affected, comma separated, use lib/ directory names please]
+
+For more information about committing, see CONTRIBUTING.md
diff --git a/sonar-project.properties b/sonar-project.properties
index 6bc9989..bd5ecc2 100755
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -16,7 +16,7 @@
 services that work efficiently and seamlessly between all major languages.
 
 # Apache Thrift Version
-sonar.projectVersion=0.11.0
+sonar.projectVersion=1.0.0
 # use this to set another version string
 # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD`
 # set projectDate in combination with projectVersion for imports of old releases
@@ -31,7 +31,7 @@
 sonar.sourceEncoding=UTF-8
 
 # scm
-sonar.scm.url=scm:git:https://git-wip-us.apache.org/repos/asf/thrift
+sonar.scm.url=scm:git:https://github.com/apache/thrift.git
 
 # cppcheck -q --error-exitcode=0 --xml . 2> cppcheck-result.xml
 sonar.cxx.cppcheck.reportPath=cppcheck-result.xml
@@ -54,15 +54,15 @@
 module1.sonar.projectBaseDir=lib/java
 module1.sonar.sources=src
 module1.sonar.tests=test
-module1.sonar.binaries=build/libthrift-0.11.0.jar
-module1.sonar.libraries=build/lib/*.jar
+module1.sonar.binaries=build/libs/libthrift-1.0.0.jar
+module1.sonar.libraries=build/deps/*.jar
 module1.sonar.language=java
 
 module2.sonar.projectName=Apache Thrift - Java Tutorial
 module2.sonar.projectBaseDir=.
 module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java
 module2.sonar.binaries=tutorial/java/tutorial.jar
-module2.sonar.libraries=lib/java/build/lib/*.jar,lib/java/build/libthrift-0.11.0.jar
+module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-1.0.0.jar
 module2.sonar.language=java
 
 module3.sonar.projectName=Apache Thrift - JavaScript Library
diff --git a/test/DoubleConstantsTest.thrift b/test/DoubleConstantsTest.thrift
new file mode 100644
index 0000000..c9212ab
--- /dev/null
+++ b/test/DoubleConstantsTest.thrift
@@ -0,0 +1,17 @@
+namespace java thrift.test
+namespace cpp thrift.test
+
+// more tests on double constants (precision and type checks)
+const double DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST = 1
+const double DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST = -100
+const double DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST = 9223372036854775807
+const double DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST = -9223372036854775807
+const double DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST = 3.14159265359
+const double DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST = 1000000.1
+const double DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST = -1000000.1
+const double DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST = 1.7e+308
+const double DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST = 9223372036854775816.43
+const double DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST = -1.7e+308
+const double DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST = -9223372036854775816.43
+
+const list<double> DOUBLE_LIST_TEST = [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43]
diff --git a/test/JavaTypes.thrift b/test/JavaTypes.thrift
index fcb0ab2..8c733ad 100644
--- a/test/JavaTypes.thrift
+++ b/test/JavaTypes.thrift
@@ -96,3 +96,8 @@
     7: Map somemap,
   ) throws (1:Exception ex);
 }
+
+struct SafeBytes {
+  1: binary bytes;
+}
+
diff --git a/test/Makefile.am b/test/Makefile.am
index 335bae6..68f1986 100755
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -25,6 +25,11 @@
 PRECROSS_TARGET += precross-c_glib
 endif
 
+if WITH_CL
+SUBDIRS += cl
+PRECROSS_TARGET += precross-cl
+endif
+
 if WITH_MONO
 SUBDIRS += csharp
 PRECROSS_TARGET += precross-csharp
@@ -110,6 +115,7 @@
 	crossrunner \
 	keys \
 	c_glib \
+	cl \
 	cpp \
 	dart \
 	erl \
@@ -128,6 +134,7 @@
 	BrokenConstants.thrift \
 	ConstantsDemo.thrift \
 	DebugProtoTest.thrift \
+	DoubleConstantsTest.thrift \
 	DenseLinkingTest.thrift \
 	DocTest.thrift \
 	EnumTest.thrift \
@@ -148,6 +155,7 @@
 	StressTest.thrift \
 	ThriftTest.thrift \
 	TypedefTest.thrift \
+	UnsafeTypes.thrift \
 	known_failures_Linux.json \
 	test.py \
 	tests.json \
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index 24dcbb9..3499ab5 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -37,7 +37,7 @@
 namespace cocoa ThriftTest
 namespace lua ThriftTest
 namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest')
-namespace netcore ThriftAsync.Test
+namespace netcore ThriftTest
 
 // Presence of namespaces and sub-namespaces for which there is
 // no generator should compile with warnings only
@@ -196,7 +196,7 @@
    * @return binary  - returns the binary 'thing'
    */
   binary       testBinary(1: binary thing),
-  
+
   /**
    * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values
    * @param Xtruct thing - the Xtruct to print
diff --git a/test/php/TestPsr4.php b/test/UnsafeTypes.thrift
similarity index 91%
copy from test/php/TestPsr4.php
copy to test/UnsafeTypes.thrift
index d30bf1c..b38c905 100644
--- a/test/php/TestPsr4.php
+++ b/test/UnsafeTypes.thrift
@@ -17,7 +17,8 @@
  * under the License.
  */
 
-<?php
-$GEN_DIR = 'gen-php-psr4';
-include_once('TestClient.php');
-?>
+namespace java thrift.test
+
+struct UnsafeBytes {
+  1: binary bytes;
+}
diff --git a/test/cl/Makefile.am b/test/cl/Makefile.am
new file mode 100755
index 0000000..b5e72bc
--- /dev/null
+++ b/test/cl/Makefile.am
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+THRIFT = $(top_builddir)/compiler/cpp/thrift
+
+stubs: ../ThriftTest.thrift
+	$(THRIFT) --gen cl ../ThriftTest.thrift
+
+TestServer: make-test-server.lisp
+	$(SBCL) --script make-test-server.lisp
+
+TestClient: make-test-client.lisp
+	$(SBCL) --script make-test-client.lisp
+
+precross: stubs TestServer TestClient
+
+clean-local:
+	$(RM) -r gen-cl
+	$(RM) TestServer
+	$(RM) TestClient
+
+EXTRA_DIST = \
+	implementation.lisp \
+	make-test-client.lisp \
+	make-test-server.lisp \
+	tests.lisp
diff --git a/test/cl/implementation.lisp b/test/cl/implementation.lisp
new file mode 100644
index 0000000..0caf7be
--- /dev/null
+++ b/test/cl/implementation.lisp
@@ -0,0 +1,136 @@
+(in-package #:thrift.test-implementation)
+
+;;;; Licensed 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.
+
+(defun thrift.test.thrift-test-implementation:test-void ()
+  (format t "testVoid()~%"))
+
+(defun thrift.test.thrift-test-implementation:test-string (thing)
+  (format t "testString(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-bool (thing)
+  (format t "testBool(~a)~%" (if thing "true" "false"))
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-byte (thing)
+  (format t "testByte(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-i32 (thing)
+  (format t "testI32(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-i64 (thing)
+  (format t "testI64(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-double (thing)
+  (format t "testDouble(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-binary (thing)
+  (format t "testBinary(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-struct (thing)
+  (format t "testStruct(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-nest (thing)
+  (format t "testNest(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-map (thing)
+  (format t "testMap(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-string-map (thing)
+  (format t "testStringMap(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-set (thing)
+  (format t "testSet(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-list (thing)
+  (format t "testList(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-enum (thing)
+  (format t "testEnum(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-typedef (thing)
+  (format t "testTypedef(~a)~%" thing)
+  thing)
+
+(defun thrift.test.thrift-test-implementation:test-map-map (hello)
+  (format t "testMapMap(~a)~%" hello)
+  '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4)))))
+
+(defun thrift.test.thrift-test-implementation:test-insanity (argument)
+  (let ((result `((1 . ((2 . ,argument) (3 . ,argument)))
+                  (2 . ((6 . ,(thrift.test::make-insanity :user-map nil :xtructs nil)))))))
+    (format t "~a~%" result)
+    result))
+
+(defun thrift.test.thrift-test-implementation:test-multi (arg0 arg1 arg2 arg3 arg4 arg5)
+  (declare (ignorable arg3 arg4 arg5))
+  (format t "testMulti()~%")
+  (thrift.test:make-xtruct :string-thing "Hello2"
+                           :byte-thing arg0
+                           :i32-thing arg1
+                           :i64-thing arg2))
+
+(defun thrift.test.thrift-test-implementation:test-exception (arg)
+  (format t "testException(~a)~%" arg)
+  (cond
+    ((string= arg "Xception") (error 'thrift.test:xception
+                                     :error-code 1001
+                                     :message arg))
+    ((string= arg "TException") (error 'thrift.test:xception
+                                       :error-code 0
+                                       :message "Stuff!"))))
+
+(defun thrift.test.thrift-test-implementation:test-multi-exception (arg0 arg1)
+  (format t "testMultiException(~a, ~a)~%" arg0 arg1)
+  (cond
+    ((string= arg0 "Xception") (error 'thrift.test:xception
+                                     :error-code 1001
+                                     :message "This is an Xception"))
+    ((string= arg0 "Xception2") (error 'thrift.test:xception2
+                                     :error-code 2002
+                                     :struct-thing (thrift.test:make-xtruct :string-thing "This is an Xception2"
+                                                                            :byte-thing 0
+                                                                            :i32-thing 0
+                                                                            :i64-thing 0))))
+  (thrift.test:make-xtruct :string-thing arg1
+                           :byte-thing 0
+                           :i32-thing 0
+                           :i64-thing 0))
+
+(defun thrift.test.thrift-test-implementation:test-oneway (seconds)
+  (format t "testOneway(~a): Sleeping...~%" seconds)
+  (sleep seconds)
+  (format t "testOneway(~a): done sleeping!~%" seconds))
+
+;;; Removed from the IDL definition.
+#+(or)
+(defun thrift.test.second-service-implementation:blah-blah ()
+  (format t "blahBlah()~%"))
+
+(defun thrift.test.second-service-implementation:secondtest-string (thing)
+  (format t "secondtestString(~a)~%" thing)
+  (concatenate 'string "testString(\"" thing "\")"))
+
diff --git a/test/cl/make-test-client.lisp b/test/cl/make-test-client.lisp
new file mode 100644
index 0000000..509669d
--- /dev/null
+++ b/test/cl/make-test-client.lisp
@@ -0,0 +1,93 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+#+(or) (when (not (boundp 'sb-impl::default-external-format)
+                 (setf sb-impl::default-external-format :UTF-8)))
+
+(require "asdf")
+(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*))
+(asdf:load-system :net.didierverna.clon)
+(asdf:load-system :fiasco)
+(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*))
+(asdf:load-system :thrift-gen-thrifttest)
+
+(net.didierverna.clon:nickname-package)
+
+(defpackage #:thrift-cross
+  (:use #:common-lisp #:fiasco)
+  (:export #:cross-test))
+
+(in-package #:thrift-cross)
+
+(defparameter *prot* nil)
+
+(load (merge-pathnames "tests.lisp" *load-truename*) :external-format :UTF-8)
+
+(clon:defsynopsis ()
+  (text :contents "The Common Lisp client for Thrift's cross-language test suite.")
+  (group (:header "Allowed options:")
+    (flag :short-name "h" :long-name "help"
+          :description "Print this help and exit.")
+    (stropt :long-name "host"
+            :description "The host to connect to."
+            :default-value "localhost"
+            :argument-name "ARG")
+    (stropt :long-name "port"
+            :description "Number of the port to listen for connections on."
+            :default-value "9090"
+            :argument-name "ARG"
+            :argument-type :optional)
+    (stropt :long-name "transport"
+            :description "Transport: transport to use (\"buffered\", \"framed\")"
+            :default-value "buffered"
+            :argument-name "ARG")
+    (stropt :long-name "protocol"
+            :description "Protocol: protocol to use (\"binary\", \"multi\")"
+            :default-value "binary"
+            :argument-name "ARG")))
+
+(defun main ()
+  "Entry point for our standalone application."
+  (clon:make-context)
+  (when (clon:getopt :short-name "h")
+    (clon:help)
+    (clon:exit))
+  (let ((port "9090")
+        (host "localhost")
+        (framed nil)
+        (multiplexed nil))
+    (clon:do-cmdline-options (option name value source)
+      (print (list option name value source))
+      (if (string= name "host")
+          (setf host value))
+      (if (string= name "port")
+          (setf port value))
+      (if (string= name "transport")
+          (cond ((string= value "buffered") (setf framed nil))
+                ((string= value "framed") (setf framed t))
+                (t (error "Unsupported transport."))))
+      (if (string= name "protocol")
+          (cond ((string= value "binary") (setf multiplexed nil))
+                ((string= value "multi") (setf multiplexed t))
+                (t (error "Unsupported protocol.")))))
+    (terpri)
+    (setf *prot* (thrift.implementation::client (puri:parse-uri
+                                                 (concatenate 'string "thrift://" host ":" port))
+                                                :framed framed
+                                                :multiplexed multiplexed))
+    (let ((result (cross-test :multiplexed multiplexed)))
+      (thrift.implementation::close *prot*)
+      (clon:exit result))))
+
+(clon:dump "TestClient" main)
diff --git a/test/cl/make-test-server.lisp b/test/cl/make-test-server.lisp
new file mode 100644
index 0000000..293c879
--- /dev/null
+++ b/test/cl/make-test-server.lisp
@@ -0,0 +1,80 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+(require "asdf")
+(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*))
+(asdf:load-system :net.didierverna.clon)
+(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*))
+(asdf:load-system :thrift-gen-thrifttest)
+(load (merge-pathnames "implementation.lisp" *load-truename*))
+
+(net.didierverna.clon:nickname-package)
+
+(clon:defsynopsis ()
+  (text :contents "The Common Lisp server for Thrift's cross-language test suite.")
+  (group (:header "Allowed options:")
+    (flag :short-name "h" :long-name "help"
+          :description "Print this help and exit.")
+    (stropt :long-name "port"
+            :description "Number of the port to listen for connections on."
+            :default-value "9090"
+            :argument-name "ARG"
+            :argument-type :optional)
+    (stropt :long-name "server-type"
+            :description "The type of server, currently only \"simple\" is available."
+            :default-value "simple"
+            :argument-name "ARG")
+    (stropt :long-name "transport"
+            :description "Transport: transport to use (\"buffered\" or \"framed\")"
+            :default-value "buffered"
+            :argument-name "ARG")
+    (stropt :long-name "protocol"
+            :description "Protocol: protocol to use (\"binary\" or \"multi\")"
+            :default-value "binary"
+            :argument-name "ARG")))
+
+(defun main ()
+  "Entry point for our standalone application."
+  (clon:make-context)
+  (when (clon:getopt :short-name "h")
+    (clon:help)
+    (clon:exit))
+  (let ((port "9090")
+        (framed nil)
+        (multiplexed nil))
+    (clon:do-cmdline-options (option name value source)
+      (print (list option name value source))
+      (if (string= name "port")
+          (setf port value))
+      (if (string= name "transport")
+          (cond ((string= value "buffered") (setf framed nil))
+                ((string= value "framed") (setf framed t))
+                (t (error "Unsupported transport."))))
+      (if (string= name "protocol")
+          (cond ((string= value "binary") (setf multiplexed nil))
+                ((string= value "multi") (setf multiplexed t))
+                (t (error "Unsupported protocol.")))))
+    (terpri)
+    (let ((services (if multiplexed
+                        (list thrift.test:thrift-test thrift.test:second-service)
+                        thrift.test:thrift-test)))
+      (thrift:serve (puri:parse-uri (concatenate 'string
+                                                 "thrift://127.0.0.1:"
+                                                 port))
+                    services
+                    :framed framed
+                    :multiplexed multiplexed)))
+  (clon:exit))
+
+(clon:dump "TestServer" main)
diff --git a/test/cl/tests.lisp b/test/cl/tests.lisp
new file mode 100644
index 0000000..c5035fd
--- /dev/null
+++ b/test/cl/tests.lisp
@@ -0,0 +1,240 @@
+(in-package #:thrift-cross)
+
+;;;; Licensed 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.
+
+;;;; The tests here only make sense in the context of a TestServer
+;;;; running and the dynamic variable thrift-cross::*prot*
+;;;; being set with a client connection to the TestServer. Normally,
+;;;; this is handled in make-test-client.lisp.
+
+
+;;; Standard Thrift cross-test error codes
+(defparameter *test_basetypes* 1)
+(defparameter *test_structs* 2)
+(defparameter *test_containers* 4)
+(defparameter *test_exceptions* 8)
+(defparameter *test_unknown* 64)
+(defparameter *test_timeout* 128)
+
+(defun cross-test (&key (multiplexed nil))
+  "The main cross-test runner."
+  (let ((result nil))
+    (handler-case
+        (progn
+          (unless (run-package-tests :package :base-types)
+            (pushnew *test_basetypes* result))
+          (unless (run-package-tests :package :structs)
+            (pushnew *test_structs* result))
+          (unless (run-package-tests :package :containers)
+            (pushnew *test_containers* result))
+          (unless (run-package-tests :package :exceptions)
+            (pushnew *test_exceptions* result))
+          (unless (run-package-tests :package :misc)
+            (pushnew *test_unknown* result))
+
+          ;; It doesn't seem like anyone actually uses
+          ;; the second test service when testing multiplexing,
+          ;; so this would fail against servers in other
+          ;; languages. For now, anyway.
+          #+(or)
+          (when multiplexed
+            (unless (run-package-tests :package :multiplex)
+              (pushnew *test_unknown* result))))
+      (error (e) (pushnew *test_unknown* result)))
+    (apply #'+ result)))
+
+(fiasco:define-test-package #:base-types)
+
+(in-package #:base-types)
+
+(defconstant *lang-string* "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語")
+
+(defparameter *trick-string* (format nil "quote: \" backslash: \\ newline: ~% backspace: ~C ~
+                                          tab: ~T junk: !@#$%&()(&%$#{}{}<><><" #\backspace))
+
+(defconstant *binary-sequence* #(128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127))
+
+(deftest void-test ()
+  (is (null (thrift.test.thrift-test:test-void thrift-cross::*prot*))))
+
+(deftest boolean-test ()
+  (is (thrift.test.thrift-test:test-bool thrift-cross::*prot* t))
+  (is (not (thrift.test.thrift-test:test-bool thrift-cross::*prot* nil))))
+
+(deftest integer-test ()
+  (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 127) 127))
+  (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* -128) -128))
+  (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 42) 42))
+  (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 0) 0))
+  (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 0) 0))
+  (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 2147483647) 2147483647))
+  (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* -2147483648) -2147483648))
+  (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 0) 0))
+  (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 9223372036854775807) 9223372036854775807))
+  (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* -9223372036854775808) -9223372036854775808)))
+
+(deftest double-test ()
+  (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 0.0) 0))
+  (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 42.0) 42))
+  (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -555.0) -555))
+  (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -52.3678) -52.3678)))
+
+(deftest string-test ()
+  (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "") ""))
+  (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "(defun botsbuildbots () (botsbuilsbots))")
+               "(defun botsbuildbots () (botsbuilsbots))"))
+  (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *lang-string*) *lang-string*))
+  (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *trick-string*) *trick-string*)))
+
+(deftest binary-test ()
+  (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* #()) #()))
+  (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* *binary-sequence*) *binary-sequence*)))
+
+(deftest enum-test ()
+  (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.five) thrift.test:numberz.five))
+  (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.eight) thrift.test:numberz.eight))
+  (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.one) thrift.test:numberz.one)))
+
+(deftest typedef-test ()
+  (is (= (thrift.test.thrift-test:test-typedef thrift-cross::*prot* 309858235082523) 309858235082523)))
+
+(fiasco:define-test-package #:structs)
+
+(in-package #:structs)
+
+(defparameter *test-struct* (thrift.test:make-xtruct :string-thing "Hell is empty."
+                                                     :byte-thing -2
+                                                     :i32-thing 42
+                                                     :i64-thing 42424242))
+
+(defparameter *test-nest* (thrift.test:make-xtruct2 :byte-thing 42
+                                                    :struct-thing *test-struct*
+                                                    :i32-thing -42))
+
+(deftest struct-test ()
+  (let ((rec-struct (thrift.test.thrift-test:test-struct thrift-cross::*prot* *test-struct*)))
+    (is (string= (thrift.test:xtruct-string-thing *test-struct*)
+                 (thrift.test:xtruct-string-thing rec-struct)))
+    (is (= (thrift.test:xtruct-byte-thing *test-struct*)
+           (thrift.test:xtruct-byte-thing rec-struct)))
+    (is (= (thrift.test:xtruct-i32-thing *test-struct*)
+           (thrift.test:xtruct-i32-thing rec-struct)))
+    (is (= (thrift.test:xtruct-i64-thing *test-struct*)
+           (thrift.test:xtruct-i64-thing rec-struct)))))
+
+(deftest nest-test ()
+  (let* ((rec-nest (thrift.test.thrift-test:test-nest thrift-cross::*prot* *test-nest*))
+         (rec-struct (thrift.test:xtruct2-struct-thing rec-nest)))
+    (is (string= (thrift.test:xtruct-string-thing *test-struct*)
+                 (thrift.test:xtruct-string-thing rec-struct)))
+    (is (= (thrift.test:xtruct-byte-thing *test-struct*)
+           (thrift.test:xtruct-byte-thing rec-struct)))
+    (is (= (thrift.test:xtruct-i32-thing *test-struct*)
+           (thrift.test:xtruct-i32-thing rec-struct)))
+    (is (= (thrift.test:xtruct-i64-thing *test-struct*)
+           (thrift.test:xtruct-i64-thing rec-struct)))
+    (is (= (thrift.test:xtruct2-byte-thing *test-nest*)
+           (thrift.test:xtruct2-byte-thing rec-nest)))
+    (is (= (thrift.test:xtruct2-i32-thing *test-nest*)
+           (thrift.test:xtruct2-i32-thing rec-nest)))))
+
+(fiasco:define-test-package #:containers)
+
+(in-package #:containers)
+
+(deftest list-test ()
+  (is (null (thrift.test.thrift-test:test-list thrift-cross::*prot* nil)))
+  (is (equal (thrift.test.thrift-test:test-list thrift-cross::*prot* '(42 -42 0 5)) '(42 -42 0 5))))
+
+(deftest set-test ()
+  (is (null (thrift.test.thrift-test:test-set thrift-cross::*prot* nil)))
+  (is (equal (sort (thrift.test.thrift-test:test-set thrift-cross::*prot* (list 42 -42 0 5)) #'<)
+             '(-42 0 5 42))))
+
+(defun map= (map1 map2 &key (car-predicate #'equal) (cdr-predicate #'equal))
+  "Compare two assoc maps according to the predicates given."
+  (not (set-exclusive-or map1 map2 :test (lambda (el1 el2)
+                                           (and (funcall car-predicate
+                                                         (car el1)
+                                                         (car el2))
+                                                (funcall cdr-predicate
+                                                         (cdr el1)
+                                                         (cdr el2)))))))
+
+(deftest map-test ()
+  (is (null (thrift.test.thrift-test:test-map thrift-cross::*prot* nil)))
+  (is (map= (thrift.test.thrift-test:test-map thrift-cross::*prot* '((0 . 1) (42 . -42) (5 . 5)))
+            '((0 . 1) (42 . -42) (5 . 5))))
+  (is (map= (thrift.test.thrift-test:test-map-map thrift-cross::*prot* 42)
+            '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1)))
+              (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4))))
+            :cdr-predicate #'map=)))
+
+(fiasco:define-test-package #:exceptions)
+
+(in-package #:exceptions)
+
+(defun test-xception (expected-code expected-message function &rest args)
+  "A helper function to test whether xception is signalled, and whether its fields have the expected values."
+  (handler-case (progn (apply function args)
+                       nil)
+    (thrift.test:xception (ex) (and (= (thrift.test::xception-error-code ex) expected-code)
+                                    (string= (thrift.test::xception-message ex) expected-message)))))
+
+(defun test-xception2 (expected-code expected-message function &rest args)
+  "A helper function to test whether xception2 is signalled, and whether its fields have the expected values."
+  (handler-case (progn (apply function args)
+                       nil)
+    (thrift.test:xception2 (ex) (and (= (thrift.test::xception2-error-code ex) expected-code)
+                                     (string= (thrift.test::xtruct-string-thing
+                                               (thrift.test::xception2-struct-thing ex))
+                                              expected-message)))))
+
+(deftest exception-test ()
+  (is (test-xception 1001 "Xception" #'thrift.test.thrift-test:test-exception thrift-cross::*prot* "Xception"))
+  (signals thrift:application-error (thrift.test.thrift-test:test-exception thrift-cross::*prot* "TException"))
+  (finishes (thrift.test.thrift-test:test-exception thrift-cross::*prot* "success")))
+
+(deftest multi-exception-test ()
+  (is (test-xception 1001
+                     "This is an Xception"
+                     #'thrift.test.thrift-test:test-multi-exception
+                     thrift-cross::*prot*
+                     "Xception"
+                     "meaningless"))
+  (is (test-xception2 2002
+                      "This is an Xception2"
+                      #'thrift.test.thrift-test:test-multi-exception
+                      thrift-cross::*prot*
+                      "Xception2"
+                      "meaningless too!"))
+  (is (string= "foobar" (thrift.test:xtruct-string-thing
+                         (thrift.test.thrift-test:test-multi-exception thrift-cross::*prot*
+                                                           "success!"
+                                                           "foobar")))))
+
+(fiasco:define-test-package #:misc)
+
+(in-package #:misc)
+
+(deftest oneway-test ()
+  (is (null (thrift.test.thrift-test:test-oneway thrift-cross::*prot* 1))))
+
+(fiasco:define-test-package #:multiplex)
+
+(in-package #:multiplex)
+
+(deftest multiplex-test ()
+  ;; Removed from the IDL definition.
+  ;; (finishes (thrift.test.second-service:blah-blah thrift-cross::*prot*))
+  (is (string= "asd" (thrift.test.second-service:secondtest-string thrift-cross::*prot* "asd"))))
diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt
index cdd63db..95d2991 100755
--- a/test/cpp/CMakeLists.txt
+++ b/test/cpp/CMakeLists.txt
@@ -28,6 +28,9 @@
 find_package(Libevent REQUIRED)  # Libevent comes with CMake support from upstream
 include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS})
 
+find_package(ZLIB REQUIRED)
+include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})
+
 #Make sure gen-cpp files can be included
 include_directories("${CMAKE_CURRENT_BINARY_DIR}")
 include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp")
diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp
index 5ff5e44..585f89a 100644
--- a/test/cpp/src/StressTest.cpp
+++ b/test/cpp/src/StressTest.cpp
@@ -31,7 +31,6 @@
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TFileTransport.h>
 #include <thrift/TLogging.h>
-#include <thrift/stdcxx.h>
 
 #include "Service.h"
 #include <iostream>
@@ -108,8 +107,8 @@
 };
 class ClientThread : public Runnable {
 public:
-  ClientThread(stdcxx::shared_ptr<TTransport> transport,
-               stdcxx::shared_ptr<ServiceIf> client,
+  ClientThread(std::shared_ptr<TTransport> transport,
+               std::shared_ptr<ServiceIf> client,
                Monitor& monitor,
                size_t& workerCount,
                size_t loopCount,
@@ -225,8 +224,8 @@
     }
   }
 
-  stdcxx::shared_ptr<TTransport> _transport;
-  stdcxx::shared_ptr<ServiceIf> _client;
+  std::shared_ptr<TTransport> _transport;
+  std::shared_ptr<ServiceIf> _client;
   Monitor& _monitor;
   size_t& _workerCount;
   size_t _loopCount;
@@ -391,24 +390,24 @@
     cerr << usage.str();
   }
 
-  stdcxx::shared_ptr<PlatformThreadFactory> threadFactory
-      = stdcxx::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
+  std::shared_ptr<PlatformThreadFactory> threadFactory
+      = std::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
 
   // Dispatcher
-  stdcxx::shared_ptr<Server> serviceHandler(new Server());
+  std::shared_ptr<Server> serviceHandler(new Server());
 
   if (replayRequests) {
-    stdcxx::shared_ptr<Server> serviceHandler(new Server());
-    stdcxx::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
+    std::shared_ptr<Server> serviceHandler(new Server());
+    std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
 
     // Transports
-    stdcxx::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
+    std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
     fileTransport->setChunkSize(2 * 1024 * 1024);
     fileTransport->setMaxEventSize(1024 * 16);
     fileTransport->seekToEnd();
 
     // Protocol Factory
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
     TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);
 
@@ -418,28 +417,28 @@
 
   if (runServer) {
 
-    stdcxx::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
+    std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
 
     // Transport
-    stdcxx::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
+    std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port));
 
     // Transport Factory
-    stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
+    std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
 
     // Protocol Factory
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
     if (logRequests) {
       // initialize the log file
-      stdcxx::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
+      std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
       fileTransport->setChunkSize(2 * 1024 * 1024);
       fileTransport->setMaxEventSize(1024 * 16);
 
       transportFactory
-          = stdcxx::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
+          = std::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
     }
 
-    stdcxx::shared_ptr<TServer> server;
+    std::shared_ptr<TServer> server;
 
     if (serverType == "simple") {
 
@@ -453,7 +452,7 @@
 
     } else if (serverType == "thread-pool") {
 
-      stdcxx::shared_ptr<ThreadManager> threadManager
+      std::shared_ptr<ThreadManager> threadManager
           = ThreadManager::newSimpleThreadManager(workerCount);
 
       threadManager->threadFactory(threadFactory);
@@ -465,9 +464,9 @@
                                          threadManager));
     }
 
-    stdcxx::shared_ptr<TStartObserver> observer(new TStartObserver);
+    std::shared_ptr<TStartObserver> observer(new TStartObserver);
     server->setServerEventHandler(observer);
-    stdcxx::shared_ptr<Thread> serverThread = threadFactory->newThread(server);
+    std::shared_ptr<Thread> serverThread = threadFactory->newThread(server);
 
     cerr << "Starting the server on port " << port << endl;
 
@@ -486,7 +485,7 @@
 
     size_t threadCount = 0;
 
-    set<stdcxx::shared_ptr<Thread> > clientThreads;
+    set<std::shared_ptr<Thread> > clientThreads;
 
     if (callName == "echoVoid") {
       loopType = T_VOID;
@@ -505,28 +504,28 @@
     if(clientType == "regular") {
       for (size_t ix = 0; ix < clientCount; ix++) {
 
-        stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
-        stdcxx::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
-        stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
-        stdcxx::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
+        std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
+        std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
+        std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
+        std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
 
-        clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr<ClientThread>(
+        clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>(
             new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread))));
       }
     } else if(clientType == "concurrent") {
-      stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
-      stdcxx::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
-      stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
-      //stdcxx::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
-      stdcxx::shared_ptr<ServiceConcurrentClient> serviceClient(new ServiceConcurrentClient(protocol));
+      std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port));
+      std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048));
+      std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket));
+      //std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
+      std::shared_ptr<ServiceConcurrentClient> serviceClient(new ServiceConcurrentClient(protocol));
       socket->open();
       for (size_t ix = 0; ix < clientCount; ix++) {
-        clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr<ClientThread>(
+        clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>(
             new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread))));
       }
     }
 
-    for (std::set<stdcxx::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
+    for (std::set<std::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
          thread != clientThreads.end();
          thread++) {
       (*thread)->start();
@@ -559,12 +558,12 @@
     int64_t minTime = 9223372036854775807LL;
     int64_t maxTime = 0;
 
-    for (set<stdcxx::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
+    for (set<std::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
          ix != clientThreads.end();
          ix++) {
 
-      stdcxx::shared_ptr<ClientThread> client
-          = stdcxx::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
+      std::shared_ptr<ClientThread> client
+          = std::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
 
       int64_t delta = client->_endTime - client->_startTime;
 
diff --git a/test/cpp/src/StressTestNonBlocking.cpp b/test/cpp/src/StressTestNonBlocking.cpp
index e68988f..1d3ed73 100644
--- a/test/cpp/src/StressTestNonBlocking.cpp
+++ b/test/cpp/src/StressTestNonBlocking.cpp
@@ -33,7 +33,6 @@
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TFileTransport.h>
 #include <thrift/TLogging.h>
-#include <thrift/stdcxx.h>
 
 #include "Service.h"
 
@@ -109,8 +108,8 @@
 
 class ClientThread : public Runnable {
 public:
-  ClientThread(stdcxx::shared_ptr<TTransport> transport,
-               stdcxx::shared_ptr<ServiceClient> client,
+  ClientThread(std::shared_ptr<TTransport> transport,
+               std::shared_ptr<ServiceClient> client,
                Monitor& monitor,
                size_t& workerCount,
                size_t loopCount,
@@ -221,8 +220,8 @@
     }
   }
 
-  stdcxx::shared_ptr<TTransport> _transport;
-  stdcxx::shared_ptr<ServiceClient> _client;
+  std::shared_ptr<TTransport> _transport;
+  std::shared_ptr<ServiceClient> _client;
   Monitor& _monitor;
   size_t& _workerCount;
   size_t _loopCount;
@@ -344,24 +343,24 @@
     cerr << usage.str();
   }
 
-  stdcxx::shared_ptr<PlatformThreadFactory> threadFactory
-      = stdcxx::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
+  std::shared_ptr<PlatformThreadFactory> threadFactory
+      = std::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
 
   // Dispatcher
-  stdcxx::shared_ptr<Server> serviceHandler(new Server());
+  std::shared_ptr<Server> serviceHandler(new Server());
 
   if (replayRequests) {
-    stdcxx::shared_ptr<Server> serviceHandler(new Server());
-    stdcxx::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
+    std::shared_ptr<Server> serviceHandler(new Server());
+    std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
 
     // Transports
-    stdcxx::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
+    std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
     fileTransport->setChunkSize(2 * 1024 * 1024);
     fileTransport->setMaxEventSize(1024 * 16);
     fileTransport->seekToEnd();
 
     // Protocol Factory
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
     TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);
 
@@ -371,50 +370,50 @@
 
   if (runServer) {
 
-    stdcxx::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
+    std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler));
 
     // Protocol Factory
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
     // Transport Factory
-    stdcxx::shared_ptr<TTransportFactory> transportFactory;
+    std::shared_ptr<TTransportFactory> transportFactory;
 
     if (logRequests) {
       // initialize the log file
-      stdcxx::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
+      std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath));
       fileTransport->setChunkSize(2 * 1024 * 1024);
       fileTransport->setMaxEventSize(1024 * 16);
 
       transportFactory
-          = stdcxx::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
+          = std::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport));
     }
 
-    stdcxx::shared_ptr<Thread> serverThread;
-    stdcxx::shared_ptr<Thread> serverThread2;
-    stdcxx::shared_ptr<transport::TNonblockingServerSocket> nbSocket1;
-    stdcxx::shared_ptr<transport::TNonblockingServerSocket> nbSocket2;
+    std::shared_ptr<Thread> serverThread;
+    std::shared_ptr<Thread> serverThread2;
+    std::shared_ptr<transport::TNonblockingServerSocket> nbSocket1;
+    std::shared_ptr<transport::TNonblockingServerSocket> nbSocket2;
 
     if (serverType == "simple") {
 
       nbSocket1.reset(new transport::TNonblockingServerSocket(port));
-      serverThread = threadFactory->newThread(stdcxx::shared_ptr<TServer>(
+      serverThread = threadFactory->newThread(std::shared_ptr<TServer>(
           new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1)));
       nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1));
-      serverThread2 = threadFactory->newThread(stdcxx::shared_ptr<TServer>(
+      serverThread2 = threadFactory->newThread(std::shared_ptr<TServer>(
           new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2)));
 
     } else if (serverType == "thread-pool") {
 
-      stdcxx::shared_ptr<ThreadManager> threadManager
+      std::shared_ptr<ThreadManager> threadManager
           = ThreadManager::newSimpleThreadManager(workerCount);
 
       threadManager->threadFactory(threadFactory);
       threadManager->start();
       nbSocket1.reset(new transport::TNonblockingServerSocket(port));
-      serverThread = threadFactory->newThread(stdcxx::shared_ptr<TServer>(
+      serverThread = threadFactory->newThread(std::shared_ptr<TServer>(
           new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1, threadManager)));
       nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1));
-      serverThread2 = threadFactory->newThread(stdcxx::shared_ptr<TServer>(
+      serverThread2 = threadFactory->newThread(std::shared_ptr<TServer>(
           new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2, threadManager)));
     }
 
@@ -437,7 +436,7 @@
 
     size_t threadCount = 0;
 
-    set<stdcxx::shared_ptr<Thread> > clientThreads;
+    set<std::shared_ptr<Thread> > clientThreads;
 
     if (callName == "echoVoid") {
       loopType = T_VOID;
@@ -455,16 +454,16 @@
 
     for (uint32_t ix = 0; ix < clientCount; ix++) {
 
-      stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port + (ix % 2)));
-      stdcxx::shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket));
-      stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(framedSocket));
-      stdcxx::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
+      std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port + (ix % 2)));
+      std::shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket));
+      std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(framedSocket));
+      std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol));
 
-      clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr<ClientThread>(
+      clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>(
           new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType))));
     }
 
-    for (std::set<stdcxx::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
+    for (std::set<std::shared_ptr<Thread> >::const_iterator thread = clientThreads.begin();
          thread != clientThreads.end();
          thread++) {
       (*thread)->start();
@@ -497,12 +496,12 @@
     int64_t minTime = 9223372036854775807LL;
     int64_t maxTime = 0;
 
-    for (set<stdcxx::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
+    for (set<std::shared_ptr<Thread> >::iterator ix = clientThreads.begin();
          ix != clientThreads.end();
          ix++) {
 
-      stdcxx::shared_ptr<ClientThread> client
-          = stdcxx::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
+      std::shared_ptr<ClientThread> client
+          = std::dynamic_pointer_cast<ClientThread>((*ix)->runnable());
 
       int64_t delta = client->_endTime - client->_startTime;
 
diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp
index 9544a4a..89f3fd1 100644
--- a/test/cpp/src/TestClient.cpp
+++ b/test/cpp/src/TestClient.cpp
@@ -31,6 +31,7 @@
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TSSLSocket.h>
+#include <thrift/transport/TZlibTransport.h>
 #include <thrift/async/TEvhttpClientChannel.h>
 #include <thrift/server/TNonblockingServer.h> // <event.h>
 
@@ -45,7 +46,6 @@
 #include <boost/filesystem.hpp>
 #include <boost/program_options.hpp>
 #include <boost/random/random_device.hpp>
-#include <thrift/stdcxx.h>
 #if _WIN32
 #include <thrift/windows/TWinsockSingleton.h>
 #endif
@@ -97,10 +97,10 @@
     for (int testNr = 0; testNr < 10; ++testNr) {
       std::ostringstream os;
       os << "test" << testNr;
-      client->testString(stdcxx::bind(testString_clientReturn,
+      client->testString(std::bind(testString_clientReturn,
                                     base,
                                     testNr,
-                                    stdcxx::placeholders::_1),
+                                    std::placeholders::_1),
                        os.str());
     }
   } catch (TException& exn) {
@@ -154,6 +154,7 @@
   int port = 9090;
   int numTests = 1;
   bool ssl = false;
+  bool zlib = false;
   string transport_type = "buffered";
   string protocol_type = "binary";
   string domain_socket = "";
@@ -179,12 +180,14 @@
           " (no connection with filesystem pathnames)")
       ("transport",
           boost::program_options::value<string>(&transport_type)->default_value(transport_type),
-          "Transport: buffered, framed, http, evhttp")
+          "Transport: buffered, framed, http, evhttp, zlib")
       ("protocol",
           boost::program_options::value<string>(&protocol_type)->default_value(protocol_type),
           "Protocol: binary, compact, header, json, multi, multic, multih, multij")
       ("ssl",
           "Encrypted Transport using SSL")
+      ("zlib",
+          "Wrap Transport with Zlib")
       ("testloops,n",
           boost::program_options::value<int>(&numTests)->default_value(numTests),
           "Number of Tests")
@@ -220,6 +223,8 @@
       } else if (transport_type == "framed") {
       } else if (transport_type == "http") {
       } else if (transport_type == "evhttp") {
+      } else if (transport_type == "zlib") {
+        // crosstest will pass zlib as a transport and as a flag right now..
       } else {
         throw invalid_argument("Unknown transport type " + transport_type);
       }
@@ -235,6 +240,10 @@
     ssl = true;
   }
 
+  if (vm.count("zlib")) {
+    zlib = true;
+  }
+
   if (vm.count("abstract-namespace")) {
     abstract_namespace = true;
   }
@@ -244,18 +253,18 @@
   }
 
   // THRIFT-4164: The factory MUST outlive any sockets it creates for correct behavior!
-  stdcxx::shared_ptr<TSSLSocketFactory> factory;
-  stdcxx::shared_ptr<TSocket> socket;
-  stdcxx::shared_ptr<TTransport> transport;
-  stdcxx::shared_ptr<TProtocol> protocol;
-  stdcxx::shared_ptr<TProtocol> protocol2;  // SecondService for multiplexed
+  std::shared_ptr<TSSLSocketFactory> factory;
+  std::shared_ptr<TSocket> socket;
+  std::shared_ptr<TTransport> transport;
+  std::shared_ptr<TProtocol> protocol;
+  std::shared_ptr<TProtocol> protocol2;  // SecondService for multiplexed
 
   if (ssl) {
     cout << "Client Certificate File: " << certPath << endl;
     cout << "Client Key         File: " << keyPath << endl;
     cout << "CA                 File: " << caPath << endl;
 
-    factory = stdcxx::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
+    factory = std::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
     factory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
     factory->loadTrustedCertificates(caPath.c_str());
     factory->loadCertificate(certPath.c_str());
@@ -267,41 +276,42 @@
       if (abstract_namespace) {
         std::string abstract_socket("\0", 1);
         abstract_socket += domain_socket;
-        socket = stdcxx::shared_ptr<TSocket>(new TSocket(abstract_socket));
+        socket = std::shared_ptr<TSocket>(new TSocket(abstract_socket));
       } else {
-        socket = stdcxx::shared_ptr<TSocket>(new TSocket(domain_socket));
+        socket = std::shared_ptr<TSocket>(new TSocket(domain_socket));
       }
       port = 0;
     } else {
-      socket = stdcxx::shared_ptr<TSocket>(new TSocket(host, port));
+      socket = std::shared_ptr<TSocket>(new TSocket(host, port));
     }
   }
 
   if (transport_type.compare("http") == 0) {
-    stdcxx::shared_ptr<TTransport> httpSocket(new THttpClient(socket, host, "/service"));
-    transport = httpSocket;
+    transport = std::make_shared<THttpClient>(socket, host, "/service");
   } else if (transport_type.compare("framed") == 0) {
-    stdcxx::shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket));
-    transport = framedSocket;
+    transport = std::make_shared<TFramedTransport>(socket);
   } else {
-    stdcxx::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket));
-    transport = bufferedSocket;
+    transport = std::make_shared<TBufferedTransport>(socket);
+  }
+
+  if (zlib) {
+    transport = std::make_shared<TZlibTransport>(transport);
   }
 
   if (protocol_type == "json" || protocol_type == "multij") {
-    protocol = stdcxx::make_shared<TJSONProtocol>(transport);
+    protocol = std::make_shared<TJSONProtocol>(transport);
   } else if (protocol_type == "compact" || protocol_type == "multic") {
-    protocol = stdcxx::make_shared<TCompactProtocol>(transport);
+    protocol = std::make_shared<TCompactProtocol>(transport);
   } else if (protocol_type == "header" || protocol_type == "multih") {
-    protocol = stdcxx::make_shared<THeaderProtocol>(transport);
+    protocol = std::make_shared<THeaderProtocol>(transport);
   } else {
-    protocol = stdcxx::make_shared<TBinaryProtocol>(transport);
+    protocol = std::make_shared<TBinaryProtocol>(transport);
   }
 
   if (boost::starts_with(protocol_type, "multi")) {
-  protocol2 = stdcxx::make_shared<TMultiplexedProtocol>(protocol, "SecondService");
+  protocol2 = std::make_shared<TMultiplexedProtocol>(protocol, "SecondService");
   // we don't need access to the original protocol any more, so...
-  protocol = stdcxx::make_shared<TMultiplexedProtocol>(protocol, "ThriftTest");
+  protocol = std::make_shared<TMultiplexedProtocol>(protocol, "ThriftTest");
   }
 
   // Connection info
@@ -323,14 +333,14 @@
     cout << "Libevent Features: 0x" << hex << event_base_get_features(base) << endl;
 #endif
 
-    stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
+    std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
-    stdcxx::shared_ptr<TAsyncChannel> channel(
+    std::shared_ptr<TAsyncChannel> channel(
         new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base));
     ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get());
-    client->testVoid(stdcxx::bind(testVoid_clientReturn,
+    client->testVoid(std::bind(testVoid_clientReturn,
                                 base,
-                                stdcxx::placeholders::_1));
+                                std::placeholders::_1));
 
     event_base_loop(base, 0);
     return 0;
@@ -505,8 +515,8 @@
     BASETYPE_IDENTITY_TEST(testI32, -1);
     BASETYPE_IDENTITY_TEST(testI32, 190000013);
     BASETYPE_IDENTITY_TEST(testI32, -190000013);
-    BASETYPE_IDENTITY_TEST(testI32, numeric_limits<int32_t>::max());
-    BASETYPE_IDENTITY_TEST(testI32, numeric_limits<int32_t>::min());
+    BASETYPE_IDENTITY_TEST(testI32, (numeric_limits<int32_t>::max)());
+    BASETYPE_IDENTITY_TEST(testI32, (numeric_limits<int32_t>::min)());
 
     /**
      * I64 TEST
@@ -519,8 +529,8 @@
     BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast<double>(2LL), 32));
     BASETYPE_IDENTITY_TEST(testI64, (int64_t)pow(static_cast<double>(2LL), 32) + 1);
     BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast<double>(2LL), 32) - 1);
-    BASETYPE_IDENTITY_TEST(testI64, numeric_limits<int64_t>::max());
-    BASETYPE_IDENTITY_TEST(testI64, numeric_limits<int64_t>::min());
+    BASETYPE_IDENTITY_TEST(testI64, (numeric_limits<int64_t>::max)());
+    BASETYPE_IDENTITY_TEST(testI64, (numeric_limits<int64_t>::min)());
 
     /**
      * DOUBLE TEST
@@ -946,7 +956,7 @@
         failed = true;
       } else {
         map<Numberz::type, Insanity>::const_iterator it26 = it2->second.find(Numberz::SIX);
-        if (it26 == it1->second.end() || it26->second != Insanity()) {
+        if (it26 == it2->second.end() || it26->second != Insanity()) {
           failed = true;
         }
       }
diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp
index 78b0a74..6222017 100644
--- a/test/cpp/src/TestServer.cpp
+++ b/test/cpp/src/TestServer.cpp
@@ -33,11 +33,13 @@
 #include <thrift/server/TThreadedServer.h>
 #include <thrift/transport/THttpServer.h>
 #include <thrift/transport/THttpTransport.h>
+#include <thrift/transport/TNonblockingSSLServerSocket.h>
 #include <thrift/transport/TNonblockingServerSocket.h>
 #include <thrift/transport/TSSLServerSocket.h>
 #include <thrift/transport/TSSLSocket.h>
 #include <thrift/transport/TServerSocket.h>
 #include <thrift/transport/TTransportUtils.h>
+#include <thrift/transport/TZlibTransport.h>
 
 #include "SecondService.h"
 #include "ThriftTest.h"
@@ -48,6 +50,9 @@
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
 
 #include <iostream>
 #include <stdexcept>
@@ -56,9 +61,7 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/program_options.hpp>
 #include <boost/filesystem.hpp>
-#include <thrift/stdcxx.h>
 
-#include <signal.h>
 #if _WIN32
 #include <thrift/windows/TWinsockSingleton.h>
 #endif
@@ -74,6 +77,17 @@
 
 using namespace thrift::test;
 
+// to handle a controlled shutdown, signal handling is mandatory
+#ifdef HAVE_SIGNAL_H
+apache::thrift::concurrency::Monitor gMonitor;
+void signal_handler(int signum)
+{
+  if (signum == SIGINT) {
+    gMonitor.notifyAll();
+  }
+}
+#endif
+
 class TestHandler : public ThriftTestIf {
 public:
   TestHandler() {}
@@ -113,7 +127,7 @@
   void testBinary(std::string& _return, const std::string& thing) {
     std::ostringstream hexstr;
     hexstr << std::hex << thing;
-    printf("testBinary(%lu: %s)\n", thing.size(), hexstr.str().c_str());
+    printf("testBinary(%lu: %s)\n", safe_numeric_cast<unsigned long>(thing.size()), hexstr.str().c_str());
     _return = thing;
   }
 
@@ -380,66 +394,66 @@
 
 class TestHandlerAsync : public ThriftTestCobSvIf {
 public:
-  TestHandlerAsync(stdcxx::shared_ptr<TestHandler>& handler) : _delegate(handler) {}
+  TestHandlerAsync(std::shared_ptr<TestHandler>& handler) : _delegate(handler) {}
   virtual ~TestHandlerAsync() {}
 
-  virtual void testVoid(stdcxx::function<void()> cob) {
+  virtual void testVoid(std::function<void()> cob) {
     _delegate->testVoid();
     cob();
   }
 
-  virtual void testString(stdcxx::function<void(std::string const& _return)> cob,
+  virtual void testString(std::function<void(std::string const& _return)> cob,
                           const std::string& thing) {
     std::string res;
     _delegate->testString(res, thing);
     cob(res);
   }
 
-  virtual void testBool(stdcxx::function<void(bool const& _return)> cob, const bool thing) {
+  virtual void testBool(std::function<void(bool const& _return)> cob, const bool thing) {
     bool res = _delegate->testBool(thing);
     cob(res);
   }
 
-  virtual void testByte(stdcxx::function<void(int8_t const& _return)> cob, const int8_t thing) {
+  virtual void testByte(std::function<void(int8_t const& _return)> cob, const int8_t thing) {
     int8_t res = _delegate->testByte(thing);
     cob(res);
   }
 
-  virtual void testI32(stdcxx::function<void(int32_t const& _return)> cob, const int32_t thing) {
+  virtual void testI32(std::function<void(int32_t const& _return)> cob, const int32_t thing) {
     int32_t res = _delegate->testI32(thing);
     cob(res);
   }
 
-  virtual void testI64(stdcxx::function<void(int64_t const& _return)> cob, const int64_t thing) {
+  virtual void testI64(std::function<void(int64_t const& _return)> cob, const int64_t thing) {
     int64_t res = _delegate->testI64(thing);
     cob(res);
   }
 
-  virtual void testDouble(stdcxx::function<void(double const& _return)> cob, const double thing) {
+  virtual void testDouble(std::function<void(double const& _return)> cob, const double thing) {
     double res = _delegate->testDouble(thing);
     cob(res);
   }
 
-  virtual void testBinary(stdcxx::function<void(std::string const& _return)> cob,
+  virtual void testBinary(std::function<void(std::string const& _return)> cob,
                           const std::string& thing) {
     std::string res;
     _delegate->testBinary(res, thing);
     cob(res);
   }
 
-  virtual void testStruct(stdcxx::function<void(Xtruct const& _return)> cob, const Xtruct& thing) {
+  virtual void testStruct(std::function<void(Xtruct const& _return)> cob, const Xtruct& thing) {
     Xtruct res;
     _delegate->testStruct(res, thing);
     cob(res);
   }
 
-  virtual void testNest(stdcxx::function<void(Xtruct2 const& _return)> cob, const Xtruct2& thing) {
+  virtual void testNest(std::function<void(Xtruct2 const& _return)> cob, const Xtruct2& thing) {
     Xtruct2 res;
     _delegate->testNest(res, thing);
     cob(res);
   }
 
-  virtual void testMap(stdcxx::function<void(std::map<int32_t, int32_t> const& _return)> cob,
+  virtual void testMap(std::function<void(std::map<int32_t, int32_t> const& _return)> cob,
                        const std::map<int32_t, int32_t>& thing) {
     std::map<int32_t, int32_t> res;
     _delegate->testMap(res, thing);
@@ -447,40 +461,40 @@
   }
 
   virtual void testStringMap(
-      stdcxx::function<void(std::map<std::string, std::string> const& _return)> cob,
+      std::function<void(std::map<std::string, std::string> const& _return)> cob,
       const std::map<std::string, std::string>& thing) {
     std::map<std::string, std::string> res;
     _delegate->testStringMap(res, thing);
     cob(res);
   }
 
-  virtual void testSet(stdcxx::function<void(std::set<int32_t> const& _return)> cob,
+  virtual void testSet(std::function<void(std::set<int32_t> const& _return)> cob,
                        const std::set<int32_t>& thing) {
     std::set<int32_t> res;
     _delegate->testSet(res, thing);
     cob(res);
   }
 
-  virtual void testList(stdcxx::function<void(std::vector<int32_t> const& _return)> cob,
+  virtual void testList(std::function<void(std::vector<int32_t> const& _return)> cob,
                         const std::vector<int32_t>& thing) {
     std::vector<int32_t> res;
     _delegate->testList(res, thing);
     cob(res);
   }
 
-  virtual void testEnum(stdcxx::function<void(Numberz::type const& _return)> cob,
+  virtual void testEnum(std::function<void(Numberz::type const& _return)> cob,
                         const Numberz::type thing) {
     Numberz::type res = _delegate->testEnum(thing);
     cob(res);
   }
 
-  virtual void testTypedef(stdcxx::function<void(UserId const& _return)> cob, const UserId thing) {
+  virtual void testTypedef(std::function<void(UserId const& _return)> cob, const UserId thing) {
     UserId res = _delegate->testTypedef(thing);
     cob(res);
   }
 
   virtual void testMapMap(
-      stdcxx::function<void(std::map<int32_t, std::map<int32_t, int32_t> > const& _return)> cob,
+      std::function<void(std::map<int32_t, std::map<int32_t, int32_t> > const& _return)> cob,
       const int32_t hello) {
     std::map<int32_t, std::map<int32_t, int32_t> > res;
     _delegate->testMapMap(res, hello);
@@ -488,14 +502,14 @@
   }
 
   virtual void testInsanity(
-      stdcxx::function<void(std::map<UserId, std::map<Numberz::type, Insanity> > const& _return)> cob,
+      std::function<void(std::map<UserId, std::map<Numberz::type, Insanity> > const& _return)> cob,
       const Insanity& argument) {
     std::map<UserId, std::map<Numberz::type, Insanity> > res;
     _delegate->testInsanity(res, argument);
     cob(res);
   }
 
-  virtual void testMulti(stdcxx::function<void(Xtruct const& _return)> cob,
+  virtual void testMulti(std::function<void(Xtruct const& _return)> cob,
                          const int8_t arg0,
                          const int32_t arg1,
                          const int64_t arg2,
@@ -508,8 +522,8 @@
   }
 
   virtual void testException(
-      stdcxx::function<void()> cob,
-      stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob,
+      std::function<void()> cob,
+      std::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob,
       const std::string& arg) {
     try {
       _delegate->testException(arg);
@@ -521,8 +535,8 @@
   }
 
   virtual void testMultiException(
-      stdcxx::function<void(Xtruct const& _return)> cob,
-      stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob,
+      std::function<void(Xtruct const& _return)> cob,
+      std::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob,
       const std::string& arg0,
       const std::string& arg1) {
     Xtruct res;
@@ -535,13 +549,13 @@
     cob(res);
   }
 
-  virtual void testOneway(stdcxx::function<void()> cob, const int32_t secondsToSleep) {
+  virtual void testOneway(std::function<void()> cob, const int32_t secondsToSleep) {
     _delegate->testOneway(secondsToSleep);
     cob();
   }
 
 protected:
-  stdcxx::shared_ptr<TestHandler> _delegate;
+  std::shared_ptr<TestHandler> _delegate;
 };
 
 namespace po = boost::program_options;
@@ -557,6 +571,7 @@
 #endif
   int port = 9090;
   bool ssl = false;
+  bool zlib = false;
   string transport_type = "buffered";
   string protocol_type = "binary";
   string server_type = "simple";
@@ -573,9 +588,10 @@
     ("domain-socket", po::value<string>(&domain_socket) ->default_value(domain_socket), "Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)")
     ("abstract-namespace", "Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames)")
     ("server-type", po::value<string>(&server_type)->default_value(server_type), "type of server, \"simple\", \"thread-pool\", \"threaded\", or \"nonblocking\"")
-    ("transport", po::value<string>(&transport_type)->default_value(transport_type), "transport: buffered, framed, http")
+    ("transport", po::value<string>(&transport_type)->default_value(transport_type), "transport: buffered, framed, http, zlib")
     ("protocol", po::value<string>(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json, multi, multic, multih, multij")
     ("ssl", "Encrypted Transport using SSL")
+    ("zlib", "Wrapped Transport using Zlib")
     ("processor-events", "processor-events")
     ("workers,n", po::value<size_t>(&workers)->default_value(workers), "Number of thread pools workers. Only valid for thread-pool server type")
     ("string-limit", po::value<int>(&string_limit))
@@ -619,6 +635,8 @@
       if (transport_type == "buffered") {
       } else if (transport_type == "framed") {
       } else if (transport_type == "http") {
+      } else if (transport_type == "zlib") {
+        // crosstester will pass zlib as a flag and a transport right now...
       } else {
         throw invalid_argument("Unknown transport type " + transport_type);
       }
@@ -634,14 +652,24 @@
     ssl = true;
   }
 
+  if (vm.count("zlib")) {
+    zlib = true;
+  }
+
+#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
+  if (ssl) {
+    signal(SIGPIPE, SIG_IGN); // for OpenSSL, otherwise we end abruptly
+  }
+#endif
+
   if (vm.count("abstract-namespace")) {
     abstract_namespace = true;
   }
 
   // Dispatcher
-  stdcxx::shared_ptr<TProtocolFactory> protocolFactory;
+  std::shared_ptr<TProtocolFactory> protocolFactory;
   if (protocol_type == "json" || protocol_type == "multij") {
-    stdcxx::shared_ptr<TProtocolFactory> jsonProtocolFactory(new TJSONProtocolFactory());
+    std::shared_ptr<TProtocolFactory> jsonProtocolFactory(new TJSONProtocolFactory());
     protocolFactory = jsonProtocolFactory;
   } else if (protocol_type == "compact" || protocol_type == "multic") {
     TCompactProtocolFactoryT<TBufferBase> *compactProtocolFactory = new TCompactProtocolFactoryT<TBufferBase>();
@@ -649,7 +677,7 @@
     compactProtocolFactory->setStringSizeLimit(string_limit);
     protocolFactory.reset(compactProtocolFactory);
   } else if (protocol_type == "header" || protocol_type == "multih") {
-    stdcxx::shared_ptr<TProtocolFactory> headerProtocolFactory(new THeaderProtocolFactory());
+    std::shared_ptr<TProtocolFactory> headerProtocolFactory(new THeaderProtocolFactory());
     protocolFactory = headerProtocolFactory;
   } else {
     TBinaryProtocolFactoryT<TBufferBase>* binaryProtocolFactory = new TBinaryProtocolFactoryT<TBufferBase>();
@@ -659,52 +687,56 @@
   }
 
   // Processors
-  stdcxx::shared_ptr<TestHandler> testHandler(new TestHandler());
-  stdcxx::shared_ptr<TProcessor> testProcessor(new ThriftTestProcessor(testHandler));
+  std::shared_ptr<TestHandler> testHandler(new TestHandler());
+  std::shared_ptr<TProcessor> testProcessor(new ThriftTestProcessor(testHandler));
 
   if (vm.count("processor-events")) {
     testProcessor->setEventHandler(
-        stdcxx::shared_ptr<TProcessorEventHandler>(new TestProcessorEventHandler()));
+        std::shared_ptr<TProcessorEventHandler>(new TestProcessorEventHandler()));
   }
 
   // Transport
-  stdcxx::shared_ptr<TSSLSocketFactory> sslSocketFactory;
-  stdcxx::shared_ptr<TServerSocket> serverSocket;
+  std::shared_ptr<TSSLSocketFactory> sslSocketFactory;
+  std::shared_ptr<TServerSocket> serverSocket;
 
   if (ssl) {
-    sslSocketFactory = stdcxx::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
+    sslSocketFactory = std::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
     sslSocketFactory->loadCertificate(certPath.c_str());
     sslSocketFactory->loadPrivateKey(keyPath.c_str());
     sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
-    serverSocket = stdcxx::shared_ptr<TServerSocket>(new TSSLServerSocket(port, sslSocketFactory));
+    if (server_type != "nonblocking") {
+      serverSocket = std::shared_ptr<TServerSocket>(new TSSLServerSocket(port, sslSocketFactory));
+    }
   } else {
     if (domain_socket != "") {
       if (abstract_namespace) {
         std::string abstract_socket("\0", 1);
         abstract_socket += domain_socket;
-        serverSocket = stdcxx::shared_ptr<TServerSocket>(new TServerSocket(abstract_socket));
+        serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(abstract_socket));
       } else {
         unlink(domain_socket.c_str());
-        serverSocket = stdcxx::shared_ptr<TServerSocket>(new TServerSocket(domain_socket));
+        serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(domain_socket));
       }
       port = 0;
     } else {
-      serverSocket = stdcxx::shared_ptr<TServerSocket>(new TServerSocket(port));
+      serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(port));
     }
   }
 
   // Factory
-  stdcxx::shared_ptr<TTransportFactory> transportFactory;
+  std::shared_ptr<TTransportFactory> transportFactory;
 
   if (transport_type == "http" && server_type != "nonblocking") {
-    stdcxx::shared_ptr<TTransportFactory> httpTransportFactory(new THttpServerTransportFactory());
-    transportFactory = httpTransportFactory;
+    transportFactory = std::make_shared<THttpServerTransportFactory>();
   } else if (transport_type == "framed") {
-    stdcxx::shared_ptr<TTransportFactory> framedTransportFactory(new TFramedTransportFactory());
-    transportFactory = framedTransportFactory;
+    transportFactory = std::make_shared<TFramedTransportFactory>();
   } else {
-    stdcxx::shared_ptr<TTransportFactory> bufferedTransportFactory(new TBufferedTransportFactory());
-    transportFactory = bufferedTransportFactory;
+    transportFactory = std::make_shared<TBufferedTransportFactory>();
+  }
+
+  if (zlib) {
+    // hmm.. doesn't seem to be a way to make it wrap the others...
+    transportFactory = std::make_shared<TZlibTransportFactory>();
   }
 
   // Server Info
@@ -721,30 +753,28 @@
 
   // Multiplexed Processor if needed
   if (boost::starts_with(protocol_type, "multi")) {
-    stdcxx::shared_ptr<SecondHandler> secondHandler(new SecondHandler());
-    stdcxx::shared_ptr<SecondServiceProcessor> secondProcessor(new SecondServiceProcessor(secondHandler));
+    std::shared_ptr<SecondHandler> secondHandler(new SecondHandler());
+    std::shared_ptr<SecondServiceProcessor> secondProcessor(new SecondServiceProcessor(secondHandler));
 
-    stdcxx::shared_ptr<TMultiplexedProcessor> multiplexedProcessor(new TMultiplexedProcessor());
+    std::shared_ptr<TMultiplexedProcessor> multiplexedProcessor(new TMultiplexedProcessor());
     multiplexedProcessor->registerDefault(testProcessor); // non-multi clients go to the default processor (multi:binary, multic:compact, ...)
     multiplexedProcessor->registerProcessor("ThriftTest", testProcessor);
     multiplexedProcessor->registerProcessor("SecondService", secondProcessor);
-    testProcessor = stdcxx::dynamic_pointer_cast<TProcessor>(multiplexedProcessor);
+    testProcessor = std::dynamic_pointer_cast<TProcessor>(multiplexedProcessor);
   }
 
   // Server
-  stdcxx::shared_ptr<apache::thrift::server::TServer> server;
+  std::shared_ptr<apache::thrift::server::TServer> server;
 
   if (server_type == "simple") {
     server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory));
   } else if (server_type == "thread-pool") {
 
-    stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workers);
+    std::shared_ptr<PlatformThreadFactory> threadFactory
+        = std::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
 
-    stdcxx::shared_ptr<PlatformThreadFactory> threadFactory
-        = stdcxx::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
-
+    std::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workers);
     threadManager->threadFactory(threadFactory);
-
     threadManager->start();
 
     server.reset(new TThreadPoolServer(testProcessor,
@@ -753,15 +783,14 @@
                                        protocolFactory,
                                        threadManager));
   } else if (server_type == "threaded") {
-
     server.reset(
         new TThreadedServer(testProcessor, serverSocket, transportFactory, protocolFactory));
   } else if (server_type == "nonblocking") {
     if (transport_type == "http") {
-      stdcxx::shared_ptr<TestHandlerAsync> testHandlerAsync(new TestHandlerAsync(testHandler));
-      stdcxx::shared_ptr<TAsyncProcessor> testProcessorAsync(
+      std::shared_ptr<TestHandlerAsync> testHandlerAsync(new TestHandlerAsync(testHandler));
+      std::shared_ptr<TAsyncProcessor> testProcessorAsync(
           new ThriftTestAsyncProcessor(testHandlerAsync));
-      stdcxx::shared_ptr<TAsyncBufferProcessor> testBufferProcessor(
+      std::shared_ptr<TAsyncBufferProcessor> testBufferProcessor(
           new TAsyncProtocolProcessor(testProcessorAsync, protocolFactory));
 
       // not loading nonblockingServer into "server" because
@@ -769,10 +798,15 @@
       // provide a stop method.
       TEvhttpServer nonblockingServer(testBufferProcessor, port);
       nonblockingServer.serve();
-    } else {
-      stdcxx::shared_ptr<transport::TNonblockingServerSocket> nbSocket;
-      nbSocket.reset(new transport::TNonblockingServerSocket(port));
+    } else if (transport_type == "framed") {
+      std::shared_ptr<transport::TNonblockingServerTransport> nbSocket;
+      nbSocket.reset(
+          ssl ? new transport::TNonblockingSSLServerSocket(port, sslSocketFactory)
+              : new transport::TNonblockingServerSocket(port));
       server.reset(new TNonblockingServer(testProcessor, protocolFactory, nbSocket));
+    } else {
+      cerr << "server-type nonblocking requires transport of http or framed" << endl;
+      exit(1);
     }
   }
 
@@ -780,22 +814,25 @@
     if (protocol_type == "header") {
       // Tell the server to use the same protocol for input / output
       // if using header
-      server->setOutputProtocolFactory(stdcxx::shared_ptr<TProtocolFactory>());
+      server->setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>());
     }
+    
     apache::thrift::concurrency::PlatformThreadFactory factory;
     factory.setDetached(false);
-    stdcxx::shared_ptr<apache::thrift::concurrency::Runnable> serverThreadRunner(server);
-    stdcxx::shared_ptr<apache::thrift::concurrency::Thread> thread
+    std::shared_ptr<apache::thrift::concurrency::Runnable> serverThreadRunner(server);
+    std::shared_ptr<apache::thrift::concurrency::Thread> thread
         = factory.newThread(serverThreadRunner);
-    thread->start();
 
-    // HACK: cross language test suite is unable to handle cin properly
-    //       that's why we stay in a endless loop here
-    while (1) {
-    }
-    // FIXME: find another way to stop the server (e.g. a signal)
-    // cout<<"Press enter to stop the server."<<endl;
-    // cin.ignore(); //wait until a key is pressed
+#ifdef HAVE_SIGNAL_H
+    signal(SIGINT, signal_handler);
+#endif
+
+    thread->start();
+    gMonitor.waitForever();         // wait for a shutdown signal
+    
+#ifdef HAVE_SIGNAL_H
+    signal(SIGINT, SIG_DFL);
+#endif
 
     server->stop();
     thread->join();
@@ -805,3 +842,4 @@
   cout << "done." << endl;
   return 0;
 }
+
diff --git a/test/crossrunner/collect.py b/test/crossrunner/collect.py
index 03b0c36..e2d8978 100644
--- a/test/crossrunner/collect.py
+++ b/test/crossrunner/collect.py
@@ -51,6 +51,7 @@
 ]
 
 DEFAULT_MAX_DELAY = 5
+DEFAULT_SIGNAL = 1
 DEFAULT_TIMEOUT = 5
 
 
@@ -112,7 +113,7 @@
                     yield name, impl1, impl2
 
     def maybe_max(key, o1, o2, default):
-        """maximum of two if present, otherwise defult value"""
+        """maximum of two if present, otherwise default value"""
         v1 = o1.get(key)
         v2 = o2.get(key)
         return max(v1, v2) if v1 and v2 else v1 or v2 or default
@@ -138,6 +139,7 @@
                         'server': merge_metadata(sv, **{'protocol': proto1, 'transport': trans1}),
                         'client': merge_metadata(cl, **{'protocol': proto2, 'transport': trans2}),
                         'delay': maybe_max('delay', sv, cl, DEFAULT_MAX_DELAY),
+                        'stop_signal': maybe_max('stop_signal', sv, cl, DEFAULT_SIGNAL),
                         'timeout': maybe_max('timeout', sv, cl, DEFAULT_TIMEOUT),
                         'protocol': proto,
                         'transport': trans,
diff --git a/test/crossrunner/report.py b/test/crossrunner/report.py
index 76324ed..5baf161 100644
--- a/test/crossrunner/report.py
+++ b/test/crossrunner/report.py
@@ -157,9 +157,14 @@
         ])),
         'client': list(map(re.compile, [
             '[Cc]onnection refused',
-            'Could not connect to localhost',
+            'Could not connect to',
+            'Could not open UNIX ',       # domain socket (rb)
             'ECONNREFUSED',
+            'econnrefused',               # erl
+            'CONNECTION-REFUSED-ERROR',   # cl
+            'connect ENOENT',             # nodejs domain socket
             'No such file or directory',  # domain socket
+            'Sockets.TcpClient.Connect',  # csharp
         ])),
     }
 
@@ -174,6 +179,7 @@
             def match(line):
                 for expr in exprs:
                     if expr.search(line):
+                        self._log.info("maybe false positive: %s" % line)
                         return True
 
             with logfile_open(self.logpath, 'r') as fp:
@@ -204,7 +210,7 @@
     def _print_footer(self, returncode=None):
         self._print_bar()
         if returncode is not None:
-            print('Return code: %d' % returncode, file=self.out)
+            print('Return code: %d (negative values indicate kill by signal)' % returncode, file=self.out)
         else:
             print('Process is killed.', file=self.out)
         self._print_exec_time()
@@ -261,7 +267,8 @@
         if not with_result:
             return '{:24s}{:18s}{:25s}'.format(name[:23], test.protocol[:17], trans[:24])
         else:
-            return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17], trans[:24], self._result_string(test))
+            return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17],
+                                                     trans[:24], self._result_string(test))
 
     def _print_test_header(self):
         self._print_bar()
diff --git a/test/crossrunner/run.py b/test/crossrunner/run.py
index f522bb1..ef8fb60 100644
--- a/test/crossrunner/run.py
+++ b/test/crossrunner/run.py
@@ -23,19 +23,20 @@
 import os
 import platform
 import random
-import signal
 import socket
 import subprocess
 import sys
-import threading
 import time
 
 from .compat import str_join
-from .test import TestEntry, domain_socket_path
 from .report import ExecReporter, SummaryReporter
+from .test import TestEntry
+from .util import domain_socket_path
 
-RESULT_TIMEOUT = 128
 RESULT_ERROR = 64
+RESULT_TIMEOUT = 128
+SIGNONE = 0
+SIGKILL = 15
 
 # globals
 ports = None
@@ -43,35 +44,18 @@
 
 
 class ExecutionContext(object):
-    def __init__(self, cmd, cwd, env, report):
+    def __init__(self, cmd, cwd, env, stop_signal, is_server, report):
         self._log = multiprocessing.get_logger()
-        self.report = report
         self.cmd = cmd
         self.cwd = cwd
         self.env = env
-        self.timer = None
+        self.stop_signal = stop_signal
+        self.is_server = is_server
+        self.report = report
         self.expired = False
         self.killed = False
         self.proc = None
 
-    def _expire(self):
-        self._log.info('Timeout')
-        self.expired = True
-        self.kill()
-
-    def kill(self):
-        self._log.debug('Killing process : %d' % self.proc.pid)
-        self.killed = True
-        if platform.system() != 'Windows':
-            try:
-                os.killpg(self.proc.pid, signal.SIGKILL)
-            except Exception:
-                self._log.info('Failed to kill process group', exc_info=sys.exc_info())
-        try:
-            self.proc.kill()
-        except Exception:
-            self._log.info('Failed to kill process', exc_info=sys.exc_info())
-
     def _popen_args(self):
         args = {
             'cwd': self.cwd,
@@ -87,75 +71,125 @@
             args.update(preexec_fn=os.setsid)
         return args
 
-    def start(self, timeout=0):
+    def start(self):
         joined = str_join(' ', self.cmd)
         self._log.debug('COMMAND: %s', joined)
         self._log.debug('WORKDIR: %s', self.cwd)
         self._log.debug('LOGFILE: %s', self.report.logpath)
         self.report.begin()
         self.proc = subprocess.Popen(self.cmd, **self._popen_args())
-        if timeout > 0:
-            self.timer = threading.Timer(timeout, self._expire)
-            self.timer.start()
+        self._log.debug('    PID: %d', self.proc.pid)
+        self._log.debug('   PGID: %d', os.getpgid(self.proc.pid))
         return self._scoped()
 
     @contextlib.contextmanager
     def _scoped(self):
         yield self
-        self._log.debug('Killing scoped process')
-        if self.proc.poll() is None:
-            self.kill()
-            self.report.killed()
+        if self.is_server:
+            # the server is supposed to run until we stop it
+            if self.returncode is not None:
+                self.report.died()
+            else:
+                if self.stop_signal != SIGNONE:
+                    if self.sigwait(self.stop_signal):
+                        self.report.end(self.returncode)
+                    else:
+                        self.report.killed()
+                else:
+                    self.sigwait(SIGKILL)
         else:
-            self._log.debug('Process died unexpectedly')
-            self.report.died()
+            # the client is supposed to exit normally
+            if self.returncode is not None:
+                self.report.end(self.returncode)
+            else:
+                self.sigwait(SIGKILL)
+                self.report.killed()
+        self._log.debug('[{0}] exited with return code {1}'.format(self.proc.pid, self.returncode))
 
-    def wait(self):
-        self.proc.communicate()
-        if self.timer:
-            self.timer.cancel()
-        self.report.end(self.returncode)
+    # Send a signal to the process and then wait for it to end
+    # If the signal requested is SIGNONE, no signal is sent, and
+    # instead we just wait for the process to end; further if it
+    # does not end normally with SIGNONE, we mark it as expired.
+    # If the process fails to end and the signal is not SIGKILL,
+    # it re-runs with SIGKILL so that a real process kill occurs
+    # returns True if the process ended, False if it may not have
+    def sigwait(self, sig=SIGKILL, timeout=2):
+        try:
+            if sig != SIGNONE:
+                self._log.debug('[{0}] send signal {1}'.format(self.proc.pid, sig))
+                if sig == SIGKILL:
+                    self.killed = True
+                try:
+                    if platform.system() != 'Windows':
+                        os.killpg(os.getpgid(self.proc.pid), sig)
+                    else:
+                        self.proc.send_signal(sig)
+                except Exception:
+                    self._log.info('[{0}] Failed to kill process'.format(self.proc.pid), exc_info=sys.exc_info())
+            self._log.debug('[{0}] wait begin, timeout {1} sec(s)'.format(self.proc.pid, timeout))
+            self.proc.communicate(timeout=timeout)
+            self._log.debug('[{0}] process ended with return code {1}'.format(self.proc.pid, self.returncode))
+            self.report.end(self.returncode)
+            return True
+        except subprocess.TimeoutExpired:
+            self._log.info('[{0}] timeout waiting for process to end'.format(self.proc.pid))
+            if sig == SIGNONE:
+                self.expired = True
+            return False if sig == SIGKILL else self.sigwait(SIGKILL, 1)
+
+    # called on the client process to wait for it to end naturally
+    def wait(self, timeout):
+        self.sigwait(SIGNONE, timeout)
 
     @property
     def returncode(self):
         return self.proc.returncode if self.proc else None
 
 
-def exec_context(port, logdir, test, prog):
+def exec_context(port, logdir, test, prog, is_server):
     report = ExecReporter(logdir, test, prog)
     prog.build_command(port)
-    return ExecutionContext(prog.command, prog.workdir, prog.env, report)
+    return ExecutionContext(prog.command, prog.workdir, prog.env, prog.stop_signal, is_server, report)
 
 
-def run_test(testdir, logdir, test_dict, max_retry, async=True):
+def run_test(testdir, logdir, test_dict, max_retry, async_mode=True):
     logger = multiprocessing.get_logger()
 
-    def ensure_socket_open(proc, port, max_delay):
-        sleeped = 0.1
-        time.sleep(sleeped)
-        sleep_step = 0.2
+    def ensure_socket_open(sv, port, test):
+        slept = 0.1
+        time.sleep(slept)
+        sleep_step = 0.1
         while True:
-            # Create sockets every iteration because refused sockets cannot be
-            # reused on some systems.
-            sock4 = socket.socket()
-            sock6 = socket.socket(family=socket.AF_INET6)
-            try:
-                if sock4.connect_ex(('127.0.0.1', port)) == 0 \
-                        or sock6.connect_ex(('::1', port)) == 0:
-                    return True
-                if proc.poll() is not None:
-                    logger.warn('server process is exited')
-                    return False
-                if sleeped > max_delay:
-                    logger.warn('sleeped for %f seconds but server port is not open' % sleeped)
-                    return False
-                time.sleep(sleep_step)
-                sleeped += sleep_step
-            finally:
-                sock4.close()
-                sock6.close()
-        logger.debug('waited %f sec for server port open' % sleeped)
-        return True
+            if slept > test.delay:
+                logger.warn('[{0}] slept for {1} seconds but server is not open'.format(sv.proc.pid, slept))
+                return False
+            if test.socket == 'domain':
+                if not os.path.exists(domain_socket_path(port)):
+                    logger.debug('[{0}] domain(unix) socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept))
+                    time.sleep(sleep_step)
+                    slept += sleep_step
+            elif test.socket == 'abstract':
+                return True
+            else:
+                # Create sockets every iteration because refused sockets cannot be
+                # reused on some systems.
+                sock4 = socket.socket()
+                sock6 = socket.socket(family=socket.AF_INET6)
+                try:
+                    if sock4.connect_ex(('127.0.0.1', port)) == 0 \
+                            or sock6.connect_ex(('::1', port)) == 0:
+                        return True
+                    if sv.proc.poll() is not None:
+                        logger.warn('[{0}] server process is exited'.format(sv.proc.pid))
+                        return False
+                    logger.debug('[{0}] socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept))
+                    time.sleep(sleep_step)
+                    slept += sleep_step
+                finally:
+                    sock4.close()
+                    sock6.close()
+            logger.debug('[{0}] server ready - waited for {1} seconds'.format(sv.proc.pid, slept))
+            return True
 
     try:
         max_bind_retry = 3
@@ -169,31 +203,27 @@
             logger.debug('Start')
             with PortAllocator.alloc_port_scoped(ports, test.socket) as port:
                 logger.debug('Start with port %d' % port)
-                sv = exec_context(port, logdir, test, test.server)
-                cl = exec_context(port, logdir, test, test.client)
+                sv = exec_context(port, logdir, test, test.server, True)
+                cl = exec_context(port, logdir, test, test.client, False)
 
                 logger.debug('Starting server')
                 with sv.start():
-                    if test.socket in ('domain', 'abstract'):
-                        time.sleep(0.1)
-                        port_ok = True
-                    else:
-                        port_ok = ensure_socket_open(sv.proc, port, test.delay)
+                    port_ok = ensure_socket_open(sv, port, test)
                     if port_ok:
                         connect_retry_count = 0
-                        max_connect_retry = 3
-                        connect_retry_wait = 0.5
+                        max_connect_retry = 12
+                        connect_retry_wait = 0.25
                         while True:
                             if sv.proc.poll() is not None:
                                 logger.info('not starting client because server process is absent')
                                 break
                             logger.debug('Starting client')
-                            cl.start(test.timeout)
-                            logger.debug('Waiting client')
-                            cl.wait()
+                            cl.start()
+                            logger.debug('Waiting client (up to %d secs)' % test.timeout)
+                            cl.wait(test.timeout)
                             if not cl.report.maybe_false_positive() or connect_retry_count >= max_connect_retry:
                                 if connect_retry_count > 0 and connect_retry_count < max_connect_retry:
-                                    logger.warn('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait))
+                                    logger.info('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait))
                                 # Wait for 50ms to see if server does not die at the end.
                                 time.sleep(0.05)
                                 break
@@ -205,12 +235,18 @@
                 logger.warn('[%s]: Detected socket bind failure, retrying...', test.server.name)
                 bind_retry_count += 1
             else:
-                if cl.expired:
-                    result = RESULT_TIMEOUT
+                result = RESULT_TIMEOUT if cl.expired else cl.returncode if (cl.proc and cl.proc.poll()) is not None else RESULT_ERROR
+
+                # For servers that handle a controlled shutdown by signal
+                # if they are killed, or return an error code, that is a
+                # problem.  For servers that are not signal-aware, we simply
+                # kill them off; if we didn't kill them off, something else
+                # happened (crashed?)
+                if test.server.stop_signal != 0:
+                    if sv.killed or sv.returncode > 0:
+                        result |= RESULT_ERROR
                 else:
-                    result = cl.proc.returncode if cl.proc else RESULT_ERROR
                     if not sv.killed:
-                        # Server died without being killed.
                         result |= RESULT_ERROR
 
                 if result == 0 or retry_count >= max_retry:
@@ -219,13 +255,13 @@
                     logger.info('[%s-%s]: test failed, retrying...', test.server.name, test.client.name)
                     retry_count += 1
     except Exception:
-        if not async:
+        if not async_mode:
             raise
         logger.warn('Error executing [%s]', test.name, exc_info=True)
         return (retry_count, RESULT_ERROR)
     except:
         logger.info('Interrupted execution', exc_info=True)
-        if not async:
+        if not async_mode:
             raise
         stop.set()
         return (retry_count, RESULT_ERROR)
@@ -349,7 +385,7 @@
         ports = m.ports()
 
     def _dispatch_sync(self, test, cont, max_retry):
-        r = run_test(self.testdir, self.logdir, test, max_retry, False)
+        r = run_test(self.testdir, self.logdir, test, max_retry, async_mode=False)
         cont(r)
         return NonAsyncResult(r)
 
diff --git a/test/crossrunner/test.py b/test/crossrunner/test.py
index 74fd916..0e91284 100644
--- a/test/crossrunner/test.py
+++ b/test/crossrunner/test.py
@@ -22,22 +22,20 @@
 import os
 import sys
 from .compat import path_join
-from .util import merge_dict
-
-
-def domain_socket_path(port):
-    return '/tmp/ThriftTest.thrift.%d' % port
+from .util import merge_dict, domain_socket_path
 
 
 class TestProgram(object):
-    def __init__(self, kind, name, protocol, transport, socket, workdir, command, env=None,
+    def __init__(self, kind, name, protocol, transport, socket, workdir, stop_signal, command, env=None,
                  extra_args=[], extra_args2=[], join_args=False, **kwargs):
+
         self.kind = kind
         self.name = name
         self.protocol = protocol
         self.transport = transport
         self.socket = socket
         self.workdir = workdir
+        self.stop_signal = stop_signal
         self.command = None
         self._base_command = self._fix_cmd_path(command)
         if env:
@@ -68,11 +66,19 @@
             'abstract': ['--abstract-namespace', '--domain-socket=%s' % domain_socket_path(port)],
         }.get(socket, None)
 
+    def _transport_args(self, transport):
+        return {
+            'zlib': ['--zlib'],
+        }.get(transport, None)
+
     def build_command(self, port):
         cmd = copy.copy(self._base_command)
         args = copy.copy(self._extra_args2)
         args.append('--protocol=' + self.protocol)
         args.append('--transport=' + self.transport)
+        transport_args = self._transport_args(self.transport)
+        if transport_args:
+            args += transport_args
         socket_args = self._socket_args(self.socket, port)
         if socket_args:
             args += socket_args
diff --git a/test/crossrunner/util.py b/test/crossrunner/util.py
index e2d195a..c214df8 100644
--- a/test/crossrunner/util.py
+++ b/test/crossrunner/util.py
@@ -20,6 +20,10 @@
 import copy
 
 
+def domain_socket_path(port):
+    return '/tmp/ThriftTest.thrift.%d' % port
+
+
 def merge_dict(base, update):
     """Update dict concatenating list values"""
     res = copy.deepcopy(base)
diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs
index e2def42..b1101a1 100644
--- a/test/csharp/Properties/AssemblyInfo.cs
+++ b/test/csharp/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/test/csharp/TestClient.cs b/test/csharp/TestClient.cs
index 17e5978..949c06e 100644
--- a/test/csharp/TestClient.cs
+++ b/test/csharp/TestClient.cs
@@ -62,7 +62,9 @@
                         {
                             string certPath = "../keys/client.p12";
                             X509Certificate cert = new X509Certificate2(certPath, "thrift");
-                            trans = new TTLSSocket(host, port, 0, cert, (o, c, chain, errors) => true, null, SslProtocols.Tls);
+                            trans = new TTLSSocket(host, port, 0, cert, 
+                                (o, c, chain, errors) => true, 
+                                null, SslProtocols.Tls);
                         }
                         else
                         {
diff --git a/test/csharp/TestServer.cs b/test/csharp/TestServer.cs
index e9c7168..bf645c2 100644
--- a/test/csharp/TestServer.cs
+++ b/test/csharp/TestServer.cs
@@ -455,7 +455,9 @@
                     if (useEncryption)
                     {
                         string certPath = "../keys/server.p12";
-                        trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), null, null, SslProtocols.Tls);
+                        trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), 
+                            null,
+                            null, SslProtocols.Tls);
                     }
                     else
                     {
diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj
index 8fe40aa..63629eb 100644
--- a/test/csharp/ThriftTest.csproj
+++ b/test/csharp/ThriftTest.csproj
@@ -46,7 +46,7 @@
     <UpdateRequired>false</UpdateRequired>
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>0.11.0.%2a</ApplicationVersion>
+    <ApplicationVersion>1.0.0.0</ApplicationVersion>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
@@ -138,4 +138,4 @@
 "$(ProjectDir)\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25
 $(MSBuildToolsPath)\Csc.exe /t:library /out:"$(ProjectDir)ThriftImpl.dll" /recurse:"$(ProjectDir)gen-csharp"\* /reference:"$(ProjectDir)..\..\lib\csharp\bin\Debug\Thrift.dll"</PreBuildEvent>
   </PropertyGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml
index e386c0e..d1642f8 100644
--- a/test/dart/test_client/pubspec.yaml
+++ b/test/dart/test_client/pubspec.yaml
@@ -16,7 +16,7 @@
 # under the License.
 
 name: thrift_test_client
-version: 0.11.0
+version: 1.0.0
 description: A client integration test for the Dart Thrift library
 author: Apache Thrift Developers <dev@thrift.apache.org>
 homepage: http://thrift.apache.org
diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src
index b552970..80ef996 100644
--- a/test/erl/src/thrift_test.app.src
+++ b/test/erl/src/thrift_test.app.src
@@ -22,7 +22,7 @@
   {description, "Thrift cross language test"},
 
   % The version of the applicaton
-  {vsn, "0.11.0"},
+  {vsn, "1.0.0"},
 
   % All modules used by the application.
   {modules, [
diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json
index f96356d..8376968 100644
--- a/test/features/known_failures_Linux.json
+++ b/test/features/known_failures_Linux.json
@@ -1,46 +1,50 @@
 [
-  "c_glib-limit_container_length_binary_buffered-ip",
-  "c_glib-limit_string_length_binary_buffered-ip",
-  "cpp-theader_framed_binary_multih-header_buffered-ip",
-  "cpp-theader_framed_compact_multih-header_buffered-ip",
-  "cpp-theader_unframed_binary_multih-header_buffered-ip",
-  "cpp-theader_unframed_compact_multih-header_buffered-ip",
-  "csharp-limit_container_length_binary_buffered-ip",
-  "csharp-limit_container_length_compact_buffered-ip",
-  "csharp-limit_string_length_binary_buffered-ip",
-  "csharp-limit_string_length_compact_buffered-ip",
-  "d-limit_container_length_binary_buffered-ip",
-  "d-limit_container_length_compact_buffered-ip",
-  "d-limit_string_length_binary_buffered-ip",
-  "d-limit_string_length_compact_buffered-ip",
-  "erl-limit_container_length_binary_buffered-ip",
-  "erl-limit_container_length_compact_buffered-ip",
-  "erl-limit_string_length_binary_buffered-ip",
-  "erl-limit_string_length_compact_buffered-ip",
-  "go-limit_container_length_binary_buffered-ip",
-  "go-limit_container_length_compact_buffered-ip",
-  "go-limit_string_length_binary_buffered-ip",
-  "go-limit_string_length_compact_buffered-ip",
-  "hs-limit_container_length_binary_buffered-ip",
-  "hs-limit_container_length_compact_buffered-ip",
-  "hs-limit_string_length_binary_buffered-ip",
-  "hs-limit_string_length_compact_buffered-ip",
-  "nodejs-limit_container_length_binary_buffered-ip",
-  "nodejs-limit_container_length_compact_buffered-ip",
-  "nodejs-limit_string_length_binary_buffered-ip",
-  "nodejs-limit_string_length_compact_buffered-ip",
-  "perl-limit_container_length_binary_buffered-ip",
-  "perl-limit_string_length_binary_buffered-ip",
-  "rb-limit_container_length_accel-binary_buffered-ip",
-  "rb-limit_container_length_binary_buffered-ip",
-  "rb-limit_container_length_compact_buffered-ip",
-  "rb-limit_string_length_accel-binary_buffered-ip",
-  "rb-limit_string_length_binary_buffered-ip",
-  "rb-limit_string_length_compact_buffered-ip",
-  "rs-limit_container_length_binary_buffered-ip",
-  "rs-limit_container_length_compact_buffered-ip",
-  "rs-limit_container_length_multic-compact_buffered-ip",
-  "rs-limit_string_length_binary_buffered-ip",
-  "rs-limit_string_length_compact_buffered-ip",
-  "rs-limit_string_length_multic-compact_buffered-ip"
-]
\ No newline at end of file
+    "c_glib-limit_container_length_binary_buffered-ip",
+    "c_glib-limit_string_length_binary_buffered-ip",
+    "cl-limit_string_length_binary_buffered-ip",
+    "cl-limit_container_length_binary_buffered-ip",
+    "cpp-theader_framed_binary_multih-header_buffered-ip",
+    "cpp-theader_framed_compact_multih-header_buffered-ip",
+    "cpp-theader_unframed_binary_multih-header_buffered-ip",
+    "cpp-theader_unframed_compact_multih-header_buffered-ip",
+    "csharp-limit_container_length_binary_buffered-ip",
+    "csharp-limit_container_length_compact_buffered-ip",
+    "csharp-limit_string_length_binary_buffered-ip",
+    "csharp-limit_string_length_compact_buffered-ip",
+    "d-limit_container_length_binary_buffered-ip",
+    "d-limit_container_length_compact_buffered-ip",
+    "d-limit_string_length_binary_buffered-ip",
+    "d-limit_string_length_compact_buffered-ip",
+    "erl-limit_container_length_binary_buffered-ip",
+    "erl-limit_container_length_compact_buffered-ip",
+    "erl-limit_string_length_binary_buffered-ip",
+    "erl-limit_string_length_compact_buffered-ip",
+    "go-limit_container_length_binary_buffered-ip",
+    "go-limit_container_length_compact_buffered-ip",
+    "go-limit_string_length_binary_buffered-ip",
+    "go-limit_string_length_compact_buffered-ip",
+    "hs-limit_container_length_binary_buffered-ip",
+    "hs-limit_container_length_compact_buffered-ip",
+    "hs-limit_string_length_binary_buffered-ip",
+    "hs-limit_string_length_compact_buffered-ip",
+    "nodejs-limit_container_length_binary_buffered-ip",
+    "nodejs-limit_container_length_compact_buffered-ip",
+    "nodejs-limit_string_length_binary_buffered-ip",
+    "nodejs-limit_string_length_compact_buffered-ip",
+    "perl-limit_container_length_binary_buffered-ip",
+    "perl-limit_string_length_binary_buffered-ip",
+    "rb-limit_container_length_accel-binary_buffered-ip",
+    "rb-limit_container_length_binary_buffered-ip",
+    "rb-limit_container_length_compact_buffered-ip",
+    "rb-limit_string_length_accel-binary_buffered-ip",
+    "rb-limit_string_length_binary_buffered-ip",
+    "rb-limit_string_length_compact_buffered-ip",
+    "rs-limit_container_length_binary_buffered-ip",
+    "rs-limit_container_length_compact_buffered-ip",
+    "rs-limit_container_length_multic-compact_buffered-ip",
+    "rs-limit_string_length_binary_buffered-ip",
+    "rs-limit_string_length_compact_buffered-ip",
+    "rs-limit_string_length_multic-compact_buffered-ip",
+    "netcore-limit_string_length_compact_buffered-ip",
+    "netcore-limit_container_length_compact_buffered-ip"
+]
diff --git a/test/features/nosslv3.sh b/test/features/nosslv3.sh
index e550d51..38cca07 100755
--- a/test/features/nosslv3.sh
+++ b/test/features/nosslv3.sh
@@ -32,6 +32,13 @@
 {
   local nego
   local negodenied
+  local opensslv
+
+  opensslv=$(openssl version | cut -d' ' -f2)
+  if [[ $opensslv > "1.0" ]]; then
+    echo "[pass] OpenSSL 1.1 or later - no need to check ssl3"
+    return 0
+  fi
 
   # echo "openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null"
   nego=$(openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null)
diff --git a/test/go/Makefile.am b/test/go/Makefile.am
index 6bc97f5..6da8339 100644
--- a/test/go/Makefile.am
+++ b/test/go/Makefile.am
@@ -18,9 +18,6 @@
 #
 
 BUILT_SOURCES = gopath
-if GOVERSION_LT_17
-COMPILER_EXTRAFLAG=",legacy_context"
-endif
 
 THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=thrift$(COMPILER_EXTRAFLAG)
 THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift
@@ -37,7 +34,6 @@
 	mkdir -p src/gen
 	$(THRIFTCMD) ThriftTest.thrift
 	$(THRIFTCMD) ../StressTest.thrift
-	GOPATH=`pwd` $(GO) get golang.org/x/net/context
 	GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock || true
 	sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' src/github.com/golang/mock/gomock/controller.go || true
 	GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock
diff --git a/test/go/src/bin/stress/go17.go b/test/go/src/bin/stress/go17.go
deleted file mode 100644
index 81f1ad8..0000000
--- a/test/go/src/bin/stress/go17.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package main
-
-import (
-	"context"
-	"sync/atomic"
-)
-
-type handler struct{}
-
-func (h *handler) EchoVoid(ctx context.Context) (err error) {
-	atomic.AddInt64(&counter, 1)
-	return nil
-}
-func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
diff --git a/test/go/src/bin/stress/main.go b/test/go/src/bin/stress/main.go
index e8e6b2a..f2e0f20 100644
--- a/test/go/src/bin/stress/main.go
+++ b/test/go/src/bin/stress/main.go
@@ -20,6 +20,7 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"gen/stress"
@@ -216,3 +217,38 @@
 
 	done.Done()
 }
+
+type handler struct{}
+
+func (h *handler) EchoVoid(ctx context.Context) (err error) {
+	atomic.AddInt64(&counter, 1)
+	return nil
+}
+func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
+func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) {
+	atomic.AddInt64(&counter, 1)
+	return arg, nil
+}
diff --git a/test/go/src/bin/stress/pre_go17.go b/test/go/src/bin/stress/pre_go17.go
deleted file mode 100644
index 07ae5c6..0000000
--- a/test/go/src/bin/stress/pre_go17.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package main
-
-import (
-	"sync/atomic"
-
-	"golang.org/x/net/context"
-)
-
-type handler struct{}
-
-func (h *handler) EchoVoid(ctx context.Context) (err error) {
-	atomic.AddInt64(&counter, 1)
-	return nil
-}
-func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
-func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) {
-	atomic.AddInt64(&counter, 1)
-	return arg, nil
-}
diff --git a/test/go/src/bin/testclient/main.go b/test/go/src/bin/testclient/main.go
index ab24cbf..4357ee8 100644
--- a/test/go/src/bin/testclient/main.go
+++ b/test/go/src/bin/testclient/main.go
@@ -21,6 +21,7 @@
 
 import (
 	"common"
+	"context"
 	"flag"
 	"gen/thrifttest"
 	t "log"
@@ -34,6 +35,7 @@
 var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib")
 var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json")
 var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL")
+var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib")
 var testloops = flag.Int("testloops", 1, "Number of Tests")
 
 func main() {
@@ -60,6 +62,7 @@
 }
 
 var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "Xception"}
+var defaultCtx = context.Background()
 
 func callEverything(client *thrifttest.ThriftTestClient) {
 	var err error
diff --git a/test/go/src/bin/testserver/main.go b/test/go/src/bin/testserver/main.go
index 0bf833d..ca2d967 100644
--- a/test/go/src/bin/testserver/main.go
+++ b/test/go/src/bin/testserver/main.go
@@ -34,6 +34,7 @@
 var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib")
 var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json")
 var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL")
+var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib")
 var certPath = flag.String("certPath", "keys", "Directory that contains SSL certificates")
 
 func main() {
diff --git a/test/go/src/common/clientserver_test.go b/test/go/src/common/clientserver_test.go
index c4cfd44..9f93c4c 100644
--- a/test/go/src/common/clientserver_test.go
+++ b/test/go/src/common/clientserver_test.go
@@ -20,6 +20,7 @@
 package common
 
 import (
+	"context"
 	"errors"
 	"gen/thrifttest"
 	"reflect"
@@ -95,6 +96,7 @@
 }
 
 var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "some"}
+var defaultCtx = context.Background()
 
 func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, handler *MockThriftTest) {
 	gomock.InOrder(
@@ -127,12 +129,12 @@
 	)
 	var err error
 	if err = client.TestVoid(defaultCtx); err != nil {
-		t.Errorf("Unexpected error in TestVoid() call: ", err)
+		t.Errorf("Unexpected error in TestVoid() call: %s", err)
 	}
 
 	thing, err := client.TestString(defaultCtx, "thing")
 	if err != nil {
-		t.Errorf("Unexpected error in TestString() call: ", err)
+		t.Errorf("Unexpected error in TestString() call: %s", err)
 	}
 	if thing != "thing" {
 		t.Errorf("Unexpected TestString() result, expected 'thing' got '%s' ", thing)
@@ -140,22 +142,22 @@
 
 	bl, err := client.TestBool(defaultCtx, true)
 	if err != nil {
-		t.Errorf("Unexpected error in TestBool() call: ", err)
+		t.Errorf("Unexpected error in TestBool() call: %s", err)
 	}
 	if !bl {
-		t.Errorf("Unexpected TestBool() result expected true, got %f ", bl)
+		t.Errorf("Unexpected TestBool() result expected true, got %v ", bl)
 	}
 	bl, err = client.TestBool(defaultCtx, false)
 	if err != nil {
-		t.Errorf("Unexpected error in TestBool() call: ", err)
+		t.Errorf("Unexpected error in TestBool() call: %s", err)
 	}
 	if bl {
-		t.Errorf("Unexpected TestBool() result expected false, got %f ", bl)
+		t.Errorf("Unexpected TestBool() result expected false, got %v ", bl)
 	}
 
 	b, err := client.TestByte(defaultCtx, 42)
 	if err != nil {
-		t.Errorf("Unexpected error in TestByte() call: ", err)
+		t.Errorf("Unexpected error in TestByte() call: %s", err)
 	}
 	if b != 42 {
 		t.Errorf("Unexpected TestByte() result expected 42, got %d ", b)
@@ -163,7 +165,7 @@
 
 	i32, err := client.TestI32(defaultCtx, 4242)
 	if err != nil {
-		t.Errorf("Unexpected error in TestI32() call: ", err)
+		t.Errorf("Unexpected error in TestI32() call: %s", err)
 	}
 	if i32 != 4242 {
 		t.Errorf("Unexpected TestI32() result expected 4242, got %d ", i32)
@@ -171,7 +173,7 @@
 
 	i64, err := client.TestI64(defaultCtx, 424242)
 	if err != nil {
-		t.Errorf("Unexpected error in TestI64() call: ", err)
+		t.Errorf("Unexpected error in TestI64() call: %s", err)
 	}
 	if i64 != 424242 {
 		t.Errorf("Unexpected TestI64() result expected 424242, got %d ", i64)
@@ -179,7 +181,7 @@
 
 	d, err := client.TestDouble(defaultCtx, 42.42)
 	if err != nil {
-		t.Errorf("Unexpected error in TestDouble() call: ", err)
+		t.Errorf("Unexpected error in TestDouble() call: %s", err)
 	}
 	if d != 42.42 {
 		t.Errorf("Unexpected TestDouble() result expected 42.42, got %f ", d)
@@ -194,7 +196,7 @@
 	xs.I64Thing = 424242
 	xsret, err := client.TestStruct(defaultCtx, xs)
 	if err != nil {
-		t.Errorf("Unexpected error in TestStruct() call: ", err)
+		t.Errorf("Unexpected error in TestStruct() call: %s", err)
 	}
 	if *xs != *xsret {
 		t.Errorf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret)
@@ -204,7 +206,7 @@
 	x2.StructThing = xs
 	x2ret, err := client.TestNest(defaultCtx, x2)
 	if err != nil {
-		t.Errorf("Unexpected error in TestNest() call: ", err)
+		t.Errorf("Unexpected error in TestNest() call: %s", err)
 	}
 	if !reflect.DeepEqual(x2, x2ret) {
 		t.Errorf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret)
@@ -213,7 +215,7 @@
 	m := map[int32]int32{1: 2, 3: 4, 5: 42}
 	mret, err := client.TestMap(defaultCtx, m)
 	if err != nil {
-		t.Errorf("Unexpected error in TestMap() call: ", err)
+		t.Errorf("Unexpected error in TestMap() call: %s", err)
 	}
 	if !reflect.DeepEqual(m, mret) {
 		t.Errorf("Unexpected TestMap() result expected %#v, got %#v ", m, mret)
@@ -222,7 +224,7 @@
 	sm := map[string]string{"a": "2", "b": "blah", "some": "thing"}
 	smret, err := client.TestStringMap(defaultCtx, sm)
 	if err != nil {
-		t.Errorf("Unexpected error in TestStringMap() call: ", err)
+		t.Errorf("Unexpected error in TestStringMap() call: %s", err)
 	}
 	if !reflect.DeepEqual(sm, smret) {
 		t.Errorf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret)
@@ -231,7 +233,7 @@
 	s := []int32{1, 2, 42}
 	sret, err := client.TestSet(defaultCtx, s)
 	if err != nil {
-		t.Errorf("Unexpected error in TestSet() call: ", err)
+		t.Errorf("Unexpected error in TestSet() call: %s", err)
 	}
 	// Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work.
 	stemp := map[int32]struct{}{}
@@ -247,7 +249,7 @@
 	l := []int32{1, 2, 42}
 	lret, err := client.TestList(defaultCtx, l)
 	if err != nil {
-		t.Errorf("Unexpected error in TestList() call: ", err)
+		t.Errorf("Unexpected error in TestList() call: %s", err)
 	}
 	if !reflect.DeepEqual(l, lret) {
 		t.Errorf("Unexpected TestList() result expected %#v, got %#v ", l, lret)
@@ -255,7 +257,7 @@
 
 	eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO)
 	if err != nil {
-		t.Errorf("Unexpected error in TestEnum() call: ", err)
+		t.Errorf("Unexpected error in TestEnum() call: %s", err)
 	}
 	if eret != thrifttest.Numberz_TWO {
 		t.Errorf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret)
@@ -263,7 +265,7 @@
 
 	tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42))
 	if err != nil {
-		t.Errorf("Unexpected error in TestTypedef() call: ", err)
+		t.Errorf("Unexpected error in TestTypedef() call: %s", err)
 	}
 	if tret != thrifttest.UserId(42) {
 		t.Errorf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret)
@@ -271,7 +273,7 @@
 
 	mapmap, err := client.TestMapMap(defaultCtx, 42)
 	if err != nil {
-		t.Errorf("Unexpected error in TestMapmap() call: ", err)
+		t.Errorf("Unexpected error in TestMapmap() call: %s", err)
 	}
 	if !reflect.DeepEqual(mapmap, rmapmap) {
 		t.Errorf("Unexpected TestMapmap() result expected %#v, got %#v ", rmapmap, mapmap)
@@ -279,7 +281,7 @@
 
 	xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24))
 	if err != nil {
-		t.Errorf("Unexpected error in TestMulti() call: %v", err)
+		t.Errorf("Unexpected error in TestMulti() call: %s", err)
 	}
 	if !reflect.DeepEqual(xxs, xxsret) {
 		t.Errorf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret)
@@ -323,11 +325,11 @@
 
 	err = client.TestOneway(defaultCtx, 2)
 	if err != nil {
-		t.Errorf("Unexpected error in TestOneway() call: ", err)
+		t.Errorf("Unexpected error in TestOneway() call: %s", err)
 	}
 
 	//Make sure the connection still alive
 	if err = client.TestVoid(defaultCtx); err != nil {
-		t.Errorf("Unexpected error in TestVoid() call: ", err)
+		t.Errorf("Unexpected error in TestVoid() call: %s", err)
 	}
 }
diff --git a/test/go/src/common/context_test.go b/test/go/src/common/context_test.go
new file mode 100644
index 0000000..e64dbb9
--- /dev/null
+++ b/test/go/src/common/context_test.go
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package common
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"syscall"
+	"testing"
+	"thrift"
+	"time"
+)
+
+type slowHttpHandler struct{}
+
+func (slowHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	time.Sleep(1 * time.Second)
+}
+
+func TestHttpContextTimeout(t *testing.T) {
+	certPath = "../../../keys"
+
+	unit := test_unit{"127.0.0.1", 9096, "", "http", "binary", false}
+
+	server := &http.Server{Addr: unit.host + fmt.Sprintf(":%d", unit.port), Handler: slowHttpHandler{}}
+	go server.ListenAndServe()
+
+	client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl)
+	if err != nil {
+		t.Errorf("Unable to start client: %v", err)
+		return
+	}
+	defer trans.Close()
+
+	unwrapErr := func(err error) error {
+		for {
+			switch err.(type) {
+			case thrift.TTransportException:
+				err = err.(thrift.TTransportException).Err()
+			case *url.Error:
+				err = err.(*url.Error).Err
+			case *net.OpError:
+				err = err.(*net.OpError).Err
+			case *os.SyscallError:
+				err = err.(*os.SyscallError).Err
+			default:
+				return err
+			}
+		}
+	}
+
+	serverStartupDeadline := time.Now().Add(5 * time.Second)
+	for {
+		ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
+		err = client.TestVoid(ctx)
+		err = unwrapErr(err)
+		if err != syscall.ECONNREFUSED || time.Now().After(serverStartupDeadline) {
+			break
+		}
+		time.Sleep(time.Millisecond)
+	}
+
+	if err == nil {
+		t.Errorf("Request completed (should have timed out)")
+		return
+	}
+
+	// We've got to switch on `err.Error()` here since go1.7 doesn't properly return
+	// `context.DeadlineExceeded` error and `http.errRequestCanceled` is not exported.
+	// See https://github.com/golang/go/issues/17711
+	switch err.Error() {
+	case context.DeadlineExceeded.Error(), "net/http: request canceled":
+		// Expected error
+	default:
+		t.Errorf("Unexpected error: %s", err)
+	}
+}
diff --git a/test/go/src/common/go17.go b/test/go/src/common/go17.go
deleted file mode 100644
index 9aca407..0000000
--- a/test/go/src/common/go17.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package common
-
-import "context"
-
-var defaultCtx = context.Background()
diff --git a/test/go/src/common/pre_go17.go b/test/go/src/common/pre_go17.go
deleted file mode 100644
index 6c14579..0000000
--- a/test/go/src/common/pre_go17.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package common
-
-import "golang.org/x/net/context"
-
-var defaultCtx = context.Background()
diff --git a/test/go/src/common/printing_handler.go b/test/go/src/common/printing_handler.go
index c0a2862..2b22d0c 100644
--- a/test/go/src/common/printing_handler.go
+++ b/test/go/src/common/printing_handler.go
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -22,13 +20,12 @@
 package common
 
 import (
+	"context"
+	"encoding/hex"
 	"errors"
 	"fmt"
-	"encoding/hex"
 	. "gen/thrifttest"
 	"time"
-
-	"golang.org/x/net/context"
 )
 
 var PrintingHandler = &printingHandler{}
@@ -280,11 +277,11 @@
 func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) {
 	fmt.Printf("testInsanity()\n")
 	r = make(map[UserId]map[Numberz]*Insanity)
-	r[1] = map[Numberz]*Insanity {
+	r[1] = map[Numberz]*Insanity{
 		2: argument,
 		3: argument,
 	}
-	r[2] = map[Numberz]*Insanity {
+	r[2] = map[Numberz]*Insanity{
 		6: NewInsanity(),
 	}
 	return
diff --git a/test/go/src/common/printing_handler_go17.go b/test/go/src/common/printing_handler_go17.go
deleted file mode 100644
index 1efae86..0000000
--- a/test/go/src/common/printing_handler_go17.go
+++ /dev/null
@@ -1,386 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package common
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"encoding/hex"
-	. "gen/thrifttest"
-	"time"
-)
-
-var PrintingHandler = &printingHandler{}
-
-type printingHandler struct{}
-
-// Prints "testVoid()" and returns nothing.
-func (p *printingHandler) TestVoid(ctx context.Context) (err error) {
-	fmt.Println("testVoid()")
-	return nil
-}
-
-// Prints 'testString("%s")' with thing as '%s'
-// @param string thing - the string to print
-// @return string - returns the string 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestString(ctx context.Context, thing string) (r string, err error) {
-	fmt.Printf("testString(\"%s\")\n", thing)
-	return thing, nil
-}
-
-// Prints 'testBool("%t")' with thing as 'true' or 'false'
-// @param bool thing - the bool to print
-// @return bool - returns the bool 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) {
-	fmt.Printf("testBool(%t)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testByte("%d")' with thing as '%d'
-// @param byte thing - the byte to print
-// @return byte - returns the byte 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) {
-	fmt.Printf("testByte(%d)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testI32("%d")' with thing as '%d'
-// @param i32 thing - the i32 to print
-// @return i32 - returns the i32 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) {
-	fmt.Printf("testI32(%d)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testI64("%d")' with thing as '%d'
-// @param i64 thing - the i64 to print
-// @return i64 - returns the i64 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) {
-	fmt.Printf("testI64(%d)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testDouble("%f")' with thing as '%f'
-// @param double thing - the double to print
-// @return double - returns the double 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) {
-	fmt.Printf("testDouble(%f)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data
-// @param []byte thing - the binary to print
-// @return []byte - returns the binary 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) {
-	fmt.Printf("testBinary(%s)\n", hex.EncodeToString(thing))
-	return thing, nil
-}
-
-// Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values
-// @param Xtruct thing - the Xtruct to print
-// @return Xtruct - returns the Xtruct 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestStruct(ctx context.Context, thing *Xtruct) (r *Xtruct, err error) {
-	fmt.Printf("testStruct({\"%s\", %d, %d, %d})\n", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing)
-	return thing, err
-}
-
-// Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct
-// @param Xtruct2 thing - the Xtruct2 to print
-// @return Xtruct2 - returns the Xtruct2 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestNest(ctx context.Context, nest *Xtruct2) (r *Xtruct2, err error) {
-	thing := nest.StructThing
-	fmt.Printf("testNest({%d, {\"%s\", %d, %d, %d}, %d})\n", nest.ByteThing, thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing, nest.I32Thing)
-	return nest, nil
-}
-
-// Prints 'testMap("{%s")' where thing has been formatted into a string of  'key => value' pairs
-//  separated by commas and new lines
-// @param map<i32,i32> thing - the map<i32,i32> to print
-// @return map<i32,i32> - returns the map<i32,i32> 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) {
-	fmt.Printf("testMap({")
-	first := true
-	for k, v := range thing {
-		if first {
-			first = false
-		} else {
-			fmt.Printf(", ")
-		}
-		fmt.Printf("%d => %d", k, v)
-	}
-	fmt.Printf("})\n")
-	return thing, nil
-}
-
-// Prints 'testStringMap("{%s}")' where thing has been formatted into a string of  'key => value' pairs
-//  separated by commas and new lines
-// @param map<string,string> thing - the map<string,string> to print
-// @return map<string,string> - returns the map<string,string> 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) {
-	fmt.Printf("testStringMap({")
-	first := true
-	for k, v := range thing {
-		if first {
-			first = false
-		} else {
-			fmt.Printf(", ")
-		}
-		fmt.Printf("%s => %s", k, v)
-	}
-	fmt.Printf("})\n")
-	return thing, nil
-}
-
-// Prints 'testSet("{%s}")' where thing has been formatted into a string of  values
-//  separated by commas and new lines
-// @param set<i32> thing - the set<i32> to print
-// @return set<i32> - returns the set<i32> 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) {
-	fmt.Printf("testSet({")
-	first := true
-	for k, _ := range thing {
-		if first {
-			first = false
-		} else {
-			fmt.Printf(", ")
-		}
-		fmt.Printf("%d", k)
-	}
-	fmt.Printf("})\n")
-	return thing, nil
-}
-
-// Prints 'testList("{%s}")' where thing has been formatted into a string of  values
-//  separated by commas and new lines
-// @param list<i32> thing - the list<i32> to print
-// @return list<i32> - returns the list<i32> 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) {
-	fmt.Printf("testList({")
-	for i, v := range thing {
-		if i != 0 {
-			fmt.Printf(", ")
-		}
-		fmt.Printf("%d", v)
-	}
-	fmt.Printf("})\n")
-	return thing, nil
-}
-
-// Prints 'testEnum("%d")' where thing has been formatted into it's numeric value
-// @param Numberz thing - the Numberz to print
-// @return Numberz - returns the Numberz 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestEnum(ctx context.Context, thing Numberz) (r Numberz, err error) {
-	fmt.Printf("testEnum(%d)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testTypedef("%d")' with thing as '%d'
-// @param UserId thing - the UserId to print
-// @return UserId - returns the UserId 'thing'
-//
-// Parameters:
-//  - Thing
-func (p *printingHandler) TestTypedef(ctx context.Context, thing UserId) (r UserId, err error) {
-	fmt.Printf("testTypedef(%d)\n", thing)
-	return thing, nil
-}
-
-// Prints 'testMapMap("%d")' with hello as '%d'
-// @param i32 hello - the i32 to print
-// @return map<i32,map<i32,i32>> - returns a dictionary with these values:
-//   {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }
-//
-// Parameters:
-//  - Hello
-func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) {
-	fmt.Printf("testMapMap(%d)\n", hello)
-
-	r = map[int32]map[int32]int32{
-		-4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1},
-		4:  map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1},
-	}
-	return
-}
-
-// So you think you've got this all worked, out eh?
-//
-// Creates a the returned map with these values and prints it out:
-//   { 1 => { 2 => argument,
-//            3 => argument,
-//          },
-//     2 => { 6 => <empty Insanity struct>, },
-//   }
-// @return map<UserId, map<Numberz,Insanity>> - a map with the above values
-//
-// Parameters:
-//  - Argument
-func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) {
-	fmt.Printf("testInsanity()\n")
-	r = make(map[UserId]map[Numberz]*Insanity)
-	r[1] = map[Numberz]*Insanity {
-		2: argument,
-		3: argument,
-	}
-	r[2] = map[Numberz]*Insanity {
-		6: NewInsanity(),
-	}
-	return
-}
-
-// Prints 'testMulti()'
-// @param byte arg0 -
-// @param i32 arg1 -
-// @param i64 arg2 -
-// @param map<i16, string> arg3 -
-// @param Numberz arg4 -
-// @param UserId arg5 -
-// @return Xtruct - returns an Xtruct with StringThing = "Hello2, ByteThing = arg0, I32Thing = arg1
-//    and I64Thing = arg2
-//
-// Parameters:
-//  - Arg0
-//  - Arg1
-//  - Arg2
-//  - Arg3
-//  - Arg4
-//  - Arg5
-func (p *printingHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) {
-	fmt.Printf("testMulti()\n")
-	r = NewXtruct()
-
-	r.StringThing = "Hello2"
-	r.ByteThing = arg0
-	r.I32Thing = arg1
-	r.I64Thing = arg2
-	return
-}
-
-// Print 'testException(%s)' with arg as '%s'
-// @param string arg - a string indication what type of exception to throw
-// if arg == "Xception" throw Xception with errorCode = 1001 and message = arg
-// elsen if arg == "TException" throw TException
-// else do not throw anything
-//
-// Parameters:
-//  - Arg
-func (p *printingHandler) TestException(ctx context.Context, arg string) (err error) {
-	fmt.Printf("testException(%s)\n", arg)
-	switch arg {
-	case "Xception":
-		e := NewXception()
-		e.ErrorCode = 1001
-		e.Message = arg
-		return e
-	case "TException":
-		return errors.New("Just TException")
-	}
-	return
-}
-
-// Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s'
-// @param string arg - a string indication what type of exception to throw
-// if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception"
-// elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2"
-// else do not throw anything
-// @return Xtruct - an Xtruct with StringThing = arg1
-//
-// Parameters:
-//  - Arg0
-//  - Arg1
-func (p *printingHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *Xtruct, err error) {
-	fmt.Printf("testMultiException(%s, %s)\n", arg0, arg1)
-	switch arg0 {
-
-	case "Xception":
-		e := NewXception()
-		e.ErrorCode = 1001
-		e.Message = "This is an Xception"
-		return nil, e
-	case "Xception2":
-		e := NewXception2()
-		e.ErrorCode = 2002
-		e.StructThing = NewXtruct()
-		e.StructThing.StringThing = "This is an Xception2"
-		return nil, e
-	default:
-		r = NewXtruct()
-		r.StringThing = arg1
-		return
-	}
-}
-
-// Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d'
-// sleep 'secondsToSleep'
-// Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d'
-// @param i32 secondsToSleep - the number of seconds to sleep
-//
-// Parameters:
-//  - SecondsToSleep
-func (p *printingHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) {
-	fmt.Printf("testOneway(%d): Sleeping...\n", secondsToSleep)
-	time.Sleep(time.Second * time.Duration(secondsToSleep))
-	fmt.Printf("testOneway(%d): done sleeping!\n", secondsToSleep)
-	return
-}
diff --git a/test/haxe/make_all.sh b/test/haxe/make_all.sh
old mode 100644
new mode 100755
index 2621258..eb2c9c2
--- a/test/haxe/make_all.sh
+++ b/test/haxe/make_all.sh
@@ -19,7 +19,7 @@
 #
 
 # invoke Thrift comnpiler
-thrift -r -gen haxe  ../ThriftTest.thrift
+../../compiler/cpp/thrift -r -gen haxe  ../ThriftTest.thrift
 
 # output folder
 if [ ! -d bin ]; then
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index 754535f..1ab2af5 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -1,38 +1,26 @@
 [
-  "c_glib-csharp_multi-binary_buffered-ip",
-  "c_glib-csharp_multi-binary_framed-ip",
-  "c_glib-csharp_multi_buffered-ip",
-  "c_glib-csharp_multi_framed-ip",
-  "c_glib-csharp_multic-compact_buffered-ip",
-  "c_glib-csharp_multic-compact_framed-ip",
-  "c_glib-csharp_multic_buffered-ip",
-  "c_glib-csharp_multic_framed-ip",
   "c_glib-rs_multi_buffered-ip",
   "c_glib-rs_multi_framed-ip",
   "c_glib-rs_multic_buffered-ip",
   "c_glib-rs_multic_framed-ip",
-  "cpp-cpp_binary_http-domain",
-  "cpp-cpp_compact_http-domain",
-  "cpp-cpp_compact_http-ip",
-  "cpp-cpp_header_http-domain",
-  "cpp-cpp_json_http-domain",
-  "cpp-cpp_json_http-ip",
-  "cpp-cpp_multi-binary_http-domain",
-  "cpp-cpp_multi-binary_http-ip",
-  "cpp-cpp_multi_http-domain",
-  "cpp-cpp_multi_http-ip",
-  "cpp-cpp_multic-compact_http-domain",
-  "cpp-cpp_multic-compact_http-ip",
-  "cpp-cpp_multic_http-domain",
-  "cpp-cpp_multic_http-ip",
-  "cpp-cpp_multih-header_http-domain",
-  "cpp-cpp_multih-header_http-ip",
-  "cpp-cpp_multih_http-domain",
-  "cpp-cpp_multih_http-ip",
-  "cpp-cpp_multij-json_http-domain",
-  "cpp-cpp_multij-json_http-ip",
-  "cpp-cpp_multij_http-domain",
-  "cpp-cpp_multij_http-ip",
+  "cl-c_glib_binary_buffered-ip",
+  "cl-c_glib_binary_framed-ip",
+  "cl-c_glib_multi-binary_buffered-ip",
+  "cl-c_glib_multi-binary_framed-ip",
+  "cl-c_glib_multi_buffered-ip",
+  "cl-c_glib_multi_framed-ip",
+  "cl-go_binary_buffered-ip",
+  "cl-go_binary_framed-ip",
+  "cl-rb_binary-accel_buffered-ip",
+  "cl-rb_binary-accel_framed-ip",
+  "cl-rb_binary_buffered-ip",
+  "cl-rb_binary_framed-ip",
+  "cl-rs_binary_buffered-ip",
+  "cl-rs_binary_framed-ip",
+  "cl-rs_multi-binary_buffered-ip",
+  "cl-rs_multi-binary_framed-ip",
+  "cl-rs_multi_buffered-ip",
+  "cl-rs_multi_framed-ip",
   "cpp-dart_binary_http-ip",
   "cpp-dart_compact_http-ip",
   "cpp-dart_json_http-ip",
@@ -69,32 +57,106 @@
   "cpp-java_multij-json_http-ip-ssl",
   "cpp-java_multij_http-ip",
   "cpp-java_multij_http-ip-ssl",
+  "cpp-nodejs_binary_http-domain",
   "cpp-nodejs_binary_http-ip",
   "cpp-nodejs_binary_http-ip-ssl",
+  "cpp-nodejs_compact_http-domain",
   "cpp-nodejs_compact_http-ip",
   "cpp-nodejs_compact_http-ip-ssl",
+  "cpp-nodejs_json_http-domain",
   "cpp-nodejs_json_http-ip",
   "cpp-nodejs_json_http-ip-ssl",
+  "cpp-nodejs_multi-binary_http-domain",
   "cpp-nodejs_multi-binary_http-ip",
   "cpp-nodejs_multi-binary_http-ip-ssl",
+  "cpp-nodejs_multic-compact_http-domain",
   "cpp-nodejs_multic-compact_http-ip",
   "cpp-nodejs_multic-compact_http-ip-ssl",
+  "cpp-nodejs_multij-json_http-domain",
   "cpp-nodejs_multij-json_http-ip",
   "cpp-nodejs_multij-json_http-ip-ssl",
+  "cpp-py3_binary-accel_http-ip",
+  "cpp-py3_binary-accel_http-ip-ssl",
+  "cpp-py3_binary_http-ip",
+  "cpp-py3_binary_http-ip-ssl",
+  "cpp-py3_compact-accelc_http-ip",
+  "cpp-py3_compact-accelc_http-ip-ssl",
+  "cpp-py3_compact_http-ip",
+  "cpp-py3_compact_http-ip-ssl",
+  "cpp-py3_header_http-ip",
+  "cpp-py3_header_http-ip-ssl",
+  "cpp-py3_json_http-ip",
+  "cpp-py3_json_http-ip-ssl",
+  "cpp-py3_multi-accel_http-ip",
+  "cpp-py3_multi-accel_http-ip-ssl",
+  "cpp-py3_multi-binary_http-ip",
+  "cpp-py3_multi-binary_http-ip-ssl",
+  "cpp-py3_multi-multia_http-ip",
+  "cpp-py3_multi-multia_http-ip-ssl",
+  "cpp-py3_multi_http-ip",
+  "cpp-py3_multi_http-ip-ssl",
+  "cpp-py3_multic-accelc_http-ip",
+  "cpp-py3_multic-accelc_http-ip-ssl",
+  "cpp-py3_multic-compact_http-ip",
+  "cpp-py3_multic-compact_http-ip-ssl",
+  "cpp-py3_multic-multiac_http-ip",
+  "cpp-py3_multic-multiac_http-ip-ssl",
+  "cpp-py3_multic_http-ip",
+  "cpp-py3_multic_http-ip-ssl",
+  "cpp-py3_multih-header_http-ip",
+  "cpp-py3_multih-header_http-ip-ssl",
+  "cpp-py3_multij-json_http-ip",
+  "cpp-py3_multij-json_http-ip-ssl",
+  "cpp-py3_multij_http-ip",
+  "cpp-py3_multij_http-ip-ssl",
+  "cpp-py_binary-accel_http-ip",
+  "cpp-py_binary-accel_http-ip-ssl",
+  "cpp-py_binary_http-ip",
+  "cpp-py_binary_http-ip-ssl",
+  "cpp-py_compact-accelc_http-ip",
+  "cpp-py_compact-accelc_http-ip-ssl",
+  "cpp-py_compact_http-ip",
+  "cpp-py_compact_http-ip-ssl",
+  "cpp-py_header_http-ip",
+  "cpp-py_header_http-ip-ssl",
+  "cpp-py_json_http-ip",
+  "cpp-py_json_http-ip-ssl",
+  "cpp-py_multi-accel_http-ip",
+  "cpp-py_multi-accel_http-ip-ssl",
+  "cpp-py_multi-binary_http-ip",
+  "cpp-py_multi-binary_http-ip-ssl",
+  "cpp-py_multi-multia_http-ip",
+  "cpp-py_multi-multia_http-ip-ssl",
+  "cpp-py_multi_http-ip",
+  "cpp-py_multi_http-ip-ssl",
+  "cpp-py_multic-accelc_http-ip",
+  "cpp-py_multic-accelc_http-ip-ssl",
+  "cpp-py_multic-compact_http-ip",
+  "cpp-py_multic-compact_http-ip-ssl",
+  "cpp-py_multic-multiac_http-ip",
+  "cpp-py_multic-multiac_http-ip-ssl",
+  "cpp-py_multic_http-ip",
+  "cpp-py_multic_http-ip-ssl",
+  "cpp-py_multih-header_http-ip",
+  "cpp-py_multih-header_http-ip-ssl",
+  "cpp-py_multij-json_http-ip",
+  "cpp-py_multij-json_http-ip-ssl",
+  "cpp-py_multij_http-ip",
+  "cpp-py_multij_http-ip-ssl",
   "cpp-rs_multi_buffered-ip",
   "cpp-rs_multi_framed-ip",
   "cpp-rs_multic_buffered-ip",
   "cpp-rs_multic_framed-ip",
-  "csharp-d_binary_buffered-ip-ssl",
-  "csharp-d_binary_framed-ip-ssl",
-  "csharp-d_compact_buffered-ip-ssl",
-  "csharp-d_compact_framed-ip-ssl",
-  "csharp-d_json_buffered-ip-ssl",
-  "csharp-d_json_framed-ip-ssl",
-  "csharp-erl_binary_buffered-ip-ssl",
-  "csharp-erl_binary_framed-ip-ssl",
-  "csharp-erl_compact_buffered-ip-ssl",
-  "csharp-erl_compact_framed-ip-ssl",
+  "csharp-rb_binary-accel_buffered-ip-ssl",
+  "csharp-rb_binary-accel_framed-ip-ssl",
+  "csharp-rb_binary_buffered-ip-ssl",
+  "csharp-rb_binary_framed-ip-ssl",
+  "csharp-rb_compact_buffered-ip-ssl",
+  "csharp-rb_compact_framed-ip-ssl",
+  "csharp-rb_json_buffered-ip-ssl",
+  "csharp-rb_json_framed-ip-ssl",
+  "d-cl_binary_buffered-ip",
+  "d-cl_binary_framed-ip",
   "d-cpp_binary_buffered-ip",
   "d-cpp_binary_buffered-ip-ssl",
   "d-cpp_binary_framed-ip",
@@ -116,11 +178,8 @@
   "d-d_binary_http-ip",
   "d-d_compact_http-ip",
   "d-d_json_http-ip",
-  "d-dart_binary_framed-ip",
   "d-dart_binary_http-ip",
-  "d-dart_compact_framed-ip",
   "d-dart_compact_http-ip",
-  "d-dart_json_framed-ip",
   "d-dart_json_http-ip",
   "d-go_binary_http-ip",
   "d-go_binary_http-ip-ssl",
@@ -135,8 +194,6 @@
   "d-java_json_http-ip",
   "d-java_json_http-ip-ssl",
   "d-js_json_http-ip",
-  "d-lua_json_buffered-ip",
-  "d-lua_json_framed-ip",
   "d-nodejs_binary_buffered-ip",
   "d-nodejs_binary_buffered-ip-ssl",
   "d-nodejs_binary_framed-ip",
@@ -155,58 +212,86 @@
   "d-nodejs_json_framed-ip-ssl",
   "d-nodejs_json_http-ip",
   "d-nodejs_json_http-ip-ssl",
+  "d-nodets_binary_buffered-ip",
   "d-py3_binary-accel_buffered-ip",
   "d-py3_binary-accel_buffered-ip-ssl",
   "d-py3_binary-accel_framed-ip",
   "d-py3_binary-accel_framed-ip-ssl",
+  "d-py3_binary-accel_http-ip",
+  "d-py3_binary-accel_http-ip-ssl",
   "d-py3_binary_buffered-ip",
   "d-py3_binary_buffered-ip-ssl",
   "d-py3_binary_framed-ip",
   "d-py3_binary_framed-ip-ssl",
+  "d-py3_binary_http-ip",
+  "d-py3_binary_http-ip-ssl",
   "d-py3_compact-accelc_buffered-ip",
   "d-py3_compact-accelc_buffered-ip-ssl",
   "d-py3_compact-accelc_framed-ip",
   "d-py3_compact-accelc_framed-ip-ssl",
+  "d-py3_compact-accelc_http-ip",
+  "d-py3_compact-accelc_http-ip-ssl",
   "d-py3_compact_buffered-ip",
   "d-py3_compact_buffered-ip-ssl",
   "d-py3_compact_framed-ip",
   "d-py3_compact_framed-ip-ssl",
+  "d-py3_compact_http-ip",
+  "d-py3_compact_http-ip-ssl",
   "d-py3_json_buffered-ip",
   "d-py3_json_buffered-ip-ssl",
   "d-py3_json_framed-ip",
   "d-py3_json_framed-ip-ssl",
+  "d-py3_json_http-ip",
+  "d-py3_json_http-ip-ssl",
   "d-py_binary-accel_buffered-ip",
   "d-py_binary-accel_buffered-ip-ssl",
   "d-py_binary-accel_framed-ip",
   "d-py_binary-accel_framed-ip-ssl",
+  "d-py_binary-accel_http-ip",
+  "d-py_binary-accel_http-ip-ssl",
   "d-py_binary_buffered-ip",
   "d-py_binary_buffered-ip-ssl",
   "d-py_binary_framed-ip",
   "d-py_binary_framed-ip-ssl",
+  "d-py_binary_http-ip",
+  "d-py_binary_http-ip-ssl",
   "d-py_compact-accelc_buffered-ip",
   "d-py_compact-accelc_buffered-ip-ssl",
   "d-py_compact-accelc_framed-ip",
   "d-py_compact-accelc_framed-ip-ssl",
+  "d-py_compact-accelc_http-ip",
+  "d-py_compact-accelc_http-ip-ssl",
   "d-py_compact_buffered-ip",
   "d-py_compact_buffered-ip-ssl",
   "d-py_compact_framed-ip",
   "d-py_compact_framed-ip-ssl",
+  "d-py_compact_http-ip",
+  "d-py_compact_http-ip-ssl",
   "d-py_json_buffered-ip",
   "d-py_json_buffered-ip-ssl",
   "d-py_json_framed-ip",
   "d-py_json_framed-ip-ssl",
+  "d-py_json_http-ip",
+  "d-py_json_http-ip-ssl",
   "erl-cpp_binary_buffered-ip",
   "erl-cpp_compact_buffered-ip",
   "erl-csharp_binary_buffered-ip",
   "erl-csharp_compact_buffered-ip",
   "erl-nodejs_binary_buffered-ip",
   "erl-nodejs_compact_buffered-ip",
+  "erl-nodets_binary_buffered-ip",
   "erl-rb_binary-accel_buffered-ip",
+  "erl-rb_binary-accel_buffered-ip-ssl",
   "erl-rb_binary-accel_framed-ip",
+  "erl-rb_binary-accel_framed-ip-ssl",
   "erl-rb_binary_buffered-ip",
+  "erl-rb_binary_buffered-ip-ssl",
   "erl-rb_binary_framed-ip",
+  "erl-rb_binary_framed-ip-ssl",
   "erl-rb_compact_buffered-ip",
+  "erl-rb_compact_buffered-ip-ssl",
   "erl-rb_compact_framed-ip",
+  "erl-rb_compact_framed-ip-ssl",
   "go-cpp_binary_http-ip",
   "go-cpp_binary_http-ip-ssl",
   "go-cpp_compact_http-ip",
@@ -228,47 +313,32 @@
   "go-java_compact_http-ip-ssl",
   "go-java_json_http-ip",
   "go-java_json_http-ip-ssl",
-  "go-nodejs_json_framed-ip",
+  "go-py3_binary-accel_zlib-ip-ssl",
+  "go-py3_compact-accelc_zlib-ip-ssl",
+  "go-py_binary-accel_zlib-ip-ssl",
+  "go-py_compact-accelc_zlib-ip-ssl",
+  "hs-csharp_binary_buffered-ip",
   "hs-csharp_binary_framed-ip",
+  "hs-csharp_compact_buffered-ip",
   "hs-csharp_compact_framed-ip",
-  "hs-dart_binary_framed-ip",
-  "hs-dart_compact_framed-ip",
-  "hs-dart_json_framed-ip",
-  "java-d_compact_buffered-ip",
-  "java-d_compact_buffered-ip-ssl",
-  "java-d_compact_framed-ip",
+  "nodejs-cpp_binary_http-domain",
   "nodejs-cpp_binary_http-ip",
   "nodejs-cpp_binary_http-ip-ssl",
+  "nodejs-cpp_compact_http-domain",
   "nodejs-cpp_compact_http-ip",
   "nodejs-cpp_compact_http-ip-ssl",
+  "nodejs-cpp_json_buffered-ip-ssl",
+  "nodejs-cpp_json_http-domain",
   "nodejs-cpp_json_http-ip",
   "nodejs-cpp_json_http-ip-ssl",
-  "nodejs-d_binary_buffered-ip",
-  "nodejs-d_binary_buffered-ip-ssl",
-  "nodejs-d_binary_framed-ip",
-  "nodejs-d_binary_framed-ip-ssl",
   "nodejs-d_binary_http-ip",
   "nodejs-d_binary_http-ip-ssl",
-  "nodejs-d_compact_buffered-ip",
-  "nodejs-d_compact_buffered-ip-ssl",
-  "nodejs-d_compact_framed-ip",
-  "nodejs-d_compact_framed-ip-ssl",
   "nodejs-d_compact_http-ip",
   "nodejs-d_compact_http-ip-ssl",
-  "nodejs-d_json_buffered-ip",
-  "nodejs-d_json_buffered-ip-ssl",
-  "nodejs-d_json_framed-ip",
-  "nodejs-d_json_framed-ip-ssl",
   "nodejs-d_json_http-ip",
   "nodejs-d_json_http-ip-ssl",
-  "nodejs-dart_binary_buffered-ip",
-  "nodejs-dart_binary_framed-ip",
   "nodejs-dart_binary_http-ip",
-  "nodejs-dart_compact_buffered-ip",
-  "nodejs-dart_compact_framed-ip",
   "nodejs-dart_compact_http-ip",
-  "nodejs-dart_json_buffered-ip",
-  "nodejs-dart_json_framed-ip",
   "nodejs-dart_json_http-ip",
   "nodejs-go_binary_http-ip",
   "nodejs-go_binary_http-ip-ssl",
@@ -289,48 +359,136 @@
   "nodejs-lua_binary_http-ip",
   "nodejs-lua_compact_http-ip",
   "nodejs-lua_json_http-ip",
-  "nodejs-netcore_binary_buffered-ip",
-  "nodejs-netcore_binary_buffered-ip-ssl",
-  "nodejs-netcore_binary_framed-ip",
-  "nodejs-netcore_binary_framed-ip-ssl",
-  "nodejs-netcore_compact_buffered-ip",
-  "nodejs-netcore_compact_buffered-ip-ssl",
-  "nodejs-netcore_compact_framed-ip",
-  "nodejs-netcore_compact_framed-ip-ssl",
-  "nodejs-netcore_json_buffered-ip",
-  "nodejs-netcore_json_buffered-ip-ssl",
-  "nodejs-netcore_json_framed-ip",
-  "nodejs-netcore_json_framed-ip-ssl",
+  "nodejs-py3_binary-accel_http-ip",
+  "nodejs-py3_binary-accel_http-ip-ssl",
+  "nodejs-py3_binary_http-ip",
+  "nodejs-py3_binary_http-ip-ssl",
+  "nodejs-py3_compact-accelc_http-ip",
+  "nodejs-py3_compact-accelc_http-ip-ssl",
+  "nodejs-py3_compact_http-ip",
+  "nodejs-py3_compact_http-ip-ssl",
+  "nodejs-py3_json_http-ip",
+  "nodejs-py3_json_http-ip-ssl",
+  "nodejs-py_binary-accel_http-ip",
+  "nodejs-py_binary-accel_http-ip-ssl",
+  "nodejs-py_binary_http-ip",
+  "nodejs-py_binary_http-ip-ssl",
+  "nodejs-py_compact-accelc_http-ip",
+  "nodejs-py_compact-accelc_http-ip-ssl",
+  "nodejs-py_compact_http-ip",
+  "nodejs-py_compact_http-ip-ssl",
+  "nodejs-py_json_http-ip",
+  "nodejs-py_json_http-ip-ssl",
   "perl-rs_multi_buffered-ip",
   "perl-rs_multi_framed-ip",
+  "py-cpp_accel-binary_http-ip",
+  "py-cpp_accel-binary_http-ip-ssl",
+  "py-cpp_accel-binary_zlib-ip",
+  "py-cpp_accel-binary_zlib-ip-ssl",
+  "py-cpp_accelc-compact_http-ip",
+  "py-cpp_accelc-compact_http-ip-ssl",
+  "py-cpp_accelc-compact_zlib-ip",
+  "py-cpp_accelc-compact_zlib-ip-ssl",
+  "py-cpp_binary_http-ip",
+  "py-cpp_binary_http-ip-ssl",
+  "py-cpp_compact_http-ip",
+  "py-cpp_compact_http-ip-ssl",
+  "py-cpp_header_http-ip",
+  "py-cpp_header_http-ip-ssl",
+  "py-cpp_json_http-ip",
+  "py-cpp_json_http-ip-ssl",
+  "py-d_accel-binary_http-ip",
+  "py-d_accel-binary_http-ip-ssl",
+  "py-d_accelc-compact_http-ip",
+  "py-d_accelc-compact_http-ip-ssl",
+  "py-d_binary_http-ip",
+  "py-d_binary_http-ip-ssl",
+  "py-d_compact_http-ip",
+  "py-d_compact_http-ip-ssl",
+  "py-d_json_http-ip",
+  "py-d_json_http-ip-ssl",
+  "py-dart_accel-binary_http-ip",
+  "py-dart_accelc-compact_http-ip",
+  "py-dart_binary_http-ip",
+  "py-dart_compact_http-ip",
+  "py-dart_json_http-ip",
+  "py-hs_accel-binary_http-ip",
+  "py-hs_accelc-compact_http-ip",
+  "py-hs_binary_http-ip",
+  "py-hs_compact_http-ip",
+  "py-hs_header_http-ip",
+  "py-hs_json_http-ip",
+  "py-java_accel-binary_http-ip",
+  "py-java_accel-binary_http-ip-ssl",
+  "py-java_accelc-compact_http-ip",
+  "py-java_accelc-compact_http-ip-ssl",
+  "py-java_binary_http-ip",
+  "py-java_binary_http-ip-ssl",
+  "py-java_compact_http-ip",
+  "py-java_compact_http-ip-ssl",
+  "py-java_json_http-ip",
+  "py-java_json_http-ip-ssl",
+  "py-lua_accel-binary_http-ip",
+  "py-lua_accelc-compact_http-ip",
+  "py-lua_binary_http-ip",
+  "py-lua_compact_http-ip",
+  "py-lua_json_http-ip",
+  "py3-cpp_accel-binary_http-ip",
+  "py3-cpp_accel-binary_http-ip-ssl",
+  "py3-cpp_accel-binary_zlib-ip",
+  "py3-cpp_accel-binary_zlib-ip-ssl",
+  "py3-cpp_accelc-compact_http-ip",
+  "py3-cpp_accelc-compact_http-ip-ssl",
+  "py3-cpp_accelc-compact_zlib-ip",
+  "py3-cpp_accelc-compact_zlib-ip-ssl",
+  "py3-cpp_binary_http-ip",
+  "py3-cpp_binary_http-ip-ssl",
+  "py3-cpp_compact_http-ip",
+  "py3-cpp_compact_http-ip-ssl",
+  "py3-cpp_header_http-ip",
+  "py3-cpp_header_http-ip-ssl",
+  "py3-cpp_json_http-ip",
+  "py3-cpp_json_http-ip-ssl",
+  "py3-d_accel-binary_http-ip",
+  "py3-d_accel-binary_http-ip-ssl",
+  "py3-d_accelc-compact_http-ip",
+  "py3-d_accelc-compact_http-ip-ssl",
+  "py3-d_binary_http-ip",
+  "py3-d_binary_http-ip-ssl",
+  "py3-d_compact_http-ip",
+  "py3-d_compact_http-ip-ssl",
+  "py3-d_json_http-ip",
+  "py3-d_json_http-ip-ssl",
+  "py3-dart_accel-binary_http-ip",
+  "py3-dart_accelc-compact_http-ip",
+  "py3-dart_binary_http-ip",
+  "py3-dart_compact_http-ip",
+  "py3-dart_json_http-ip",
+  "py3-hs_accel-binary_http-ip",
+  "py3-hs_accelc-compact_http-ip",
+  "py3-hs_binary_http-ip",
+  "py3-hs_compact_http-ip",
+  "py3-hs_header_http-ip",
+  "py3-hs_json_http-ip",
+  "py3-java_accel-binary_http-ip",
+  "py3-java_accel-binary_http-ip-ssl",
+  "py3-java_accelc-compact_http-ip",
+  "py3-java_accelc-compact_http-ip-ssl",
+  "py3-java_binary_http-ip",
+  "py3-java_binary_http-ip-ssl",
+  "py3-java_compact_http-ip",
+  "py3-java_compact_http-ip-ssl",
+  "py3-java_json_http-ip",
+  "py3-java_json_http-ip-ssl",
+  "py3-lua_accel-binary_http-ip",
+  "py3-lua_accelc-compact_http-ip",
+  "py3-lua_binary_http-ip",
+  "py3-lua_compact_http-ip",
+  "py3-lua_json_http-ip",
+  "rb-cpp_json_buffered-domain",
   "rb-cpp_json_buffered-ip",
+  "rb-cpp_json_buffered-ip-ssl",
+  "rb-cpp_json_framed-domain",
   "rb-cpp_json_framed-ip",
-  "rs-cpp_binary_buffered-ip",
-  "rs-cpp_binary_framed-ip",
-  "rs-cpp_compact_buffered-ip",
-  "rs-cpp_compact_framed-ip",
-  "rs-cpp_multi-binary_buffered-ip",
-  "rs-cpp_multi-binary_framed-ip",
-  "rs-cpp_multi_buffered-ip",
-  "rs-cpp_multi_framed-ip",
-  "rs-cpp_multic-compact_buffered-ip",
-  "rs-cpp_multic-compact_framed-ip",
-  "rs-cpp_multic_buffered-ip",
-  "rs-cpp_multic_framed-ip",
-  "rs-csharp_binary_buffered-ip",
-  "rs-csharp_binary_framed-ip",
-  "rs-csharp_compact_buffered-ip",
-  "rs-csharp_compact_framed-ip",
-  "rs-csharp_multi-binary_buffered-ip",
-  "rs-csharp_multi-binary_framed-ip",
-  "rs-csharp_multi_buffered-ip",
-  "rs-csharp_multi_framed-ip",
-  "rs-csharp_multic-compact_buffered-ip",
-  "rs-csharp_multic-compact_framed-ip",
-  "rs-csharp_multic_buffered-ip",
-  "rs-csharp_multic_framed-ip",
-  "rs-dart_binary_framed-ip",
-  "rs-dart_compact_framed-ip",
-  "rs-dart_multi-binary_framed-ip",
-  "rs-dart_multic-compact_framed-ip"
-]
+  "rb-cpp_json_framed-ip-ssl"
+]
\ No newline at end of file
diff --git a/test/netcore/Client/.gitignore b/test/netcore/Client/.gitignore
new file mode 100644
index 0000000..67d5510
--- /dev/null
+++ b/test/netcore/Client/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/ThriftTest
diff --git a/test/netcore/Client/Client.csproj b/test/netcore/Client/Client.csproj
new file mode 100644
index 0000000..f16af39
--- /dev/null
+++ b/test/netcore/Client/Client.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Client</AssemblyName>
+    <PackageId>Client</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
+    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
+    <PackageReference Include="System.Threading" Version="[4.3,)" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+  </Target>
+</Project>
diff --git a/test/netcore/ThriftTest/Program.cs b/test/netcore/Client/Program.cs
similarity index 82%
rename from test/netcore/ThriftTest/Program.cs
rename to test/netcore/Client/Program.cs
index 94ed9d9..72139d9 100644
--- a/test/netcore/ThriftTest/Program.cs
+++ b/test/netcore/Client/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -17,9 +17,9 @@
 
 using System;
 using System.Collections.Generic;
-using Test;
+using ThriftTest;
 
-namespace ThriftTest
+namespace Client
 {
     public class Program
     {
@@ -48,8 +48,6 @@
             {
                 case "client":
                     return TestClient.Execute(subArgs);
-                case "server":
-                    return TestServer.Execute(subArgs);
                 case "--help":
                     PrintHelp();
                     return 0;
@@ -62,12 +60,10 @@
         private static void PrintHelp()
         {
             Console.WriteLine("Usage:");
-            Console.WriteLine("  ThriftTest  server  [options]'");
-            Console.WriteLine("  ThriftTest  client  [options]'");
-            Console.WriteLine("  ThriftTest  --help");
+            Console.WriteLine("  Client  client  [options]'");
+            Console.WriteLine("  Client  --help");
             Console.WriteLine("");
 
-            TestServer.PrintOptionsHelp();
             TestClient.PrintOptionsHelp();
         }
     }
diff --git a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs b/test/netcore/Client/Properties/AssemblyInfo.cs
similarity index 97%
copy from test/netcore/ThriftTest/Properties/AssemblyInfo.cs
copy to test/netcore/Client/Properties/AssemblyInfo.cs
index efc9e33..157152b 100644
--- a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs
+++ b/test/netcore/Client/Properties/AssemblyInfo.cs
@@ -22,7 +22,7 @@
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 
-[assembly: AssemblyTitle("ThriftTest")]
+[assembly: AssemblyTitle("Client")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("The Apache Software Foundation")]
diff --git a/test/netcore/ThriftTest/TestClient.cs b/test/netcore/Client/TestClient.cs
similarity index 92%
rename from test/netcore/ThriftTest/TestClient.cs
rename to test/netcore/Client/TestClient.cs
index f6cc900..8be198c 100644
--- a/test/netcore/ThriftTest/TestClient.cs
+++ b/test/netcore/Client/TestClient.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -18,28 +18,29 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Linq;
 using System.Net;
 using System.Reflection;
 using System.Security.Authentication;
 using System.Security.Cryptography.X509Certificates;
+using System.ServiceModel;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-using ThriftAsync.Test;
 using Thrift.Collections;
 using Thrift.Protocols;
 using Thrift.Transports;
 using Thrift.Transports.Client;
 
-namespace Test
+namespace ThriftTest
 {
     public class TestClient
     {
         private class TestParams
         {
             public int numIterations = 1;
-            public IPAddress host = IPAddress.Loopback;
+            public IPAddress host = IPAddress.Any;
             public int port = 9090;
             public int numThreads = 1;
             public string url;
@@ -111,11 +112,43 @@
                     }
                     else
                     {
-                        throw new ArgumentException(args[i]);
+                        //throw new ArgumentException(args[i]);
                     }
                 }
             }
 
+            private static X509Certificate2 GetClientCert()
+            {
+                var clientCertName = "client.p12";
+                var possiblePaths = new List<string>
+                {
+                    "../../../keys/",
+                    "../../keys/",
+                    "../keys/",
+                    "keys/",
+                };
+
+                string existingPath = null;
+                foreach (var possiblePath in possiblePaths)
+                {
+                    var path = Path.GetFullPath(possiblePath + clientCertName);
+                    if (File.Exists(path))
+                    {
+                        existingPath = path;
+                        break;
+                    }
+                }
+
+                if (string.IsNullOrEmpty(existingPath))
+                {
+                    throw new FileNotFoundException($"Cannot find file: {clientCertName}");
+                }
+            
+                var cert = new X509Certificate2(existingPath, "thrift");
+
+                return cert;
+            }
+            
             public TClientTransport CreateTransport()
             {
                 if (url == null)
@@ -131,9 +164,16 @@
                     {
                         if (encrypted)
                         {
-                            var certPath = "../../keys/client.p12";
-                            var cert = new X509Certificate2(certPath, "thrift");
-                            trans = new TTlsSocketClientTransport(host, port, 0, cert, (o, c, chain, errors) => true, null, SslProtocols.Tls);
+                           var cert = GetClientCert();
+                        
+                            if (cert == null || !cert.HasPrivateKey)
+                            {
+                                throw new InvalidOperationException("Certificate doesn't contain private key");
+                            }
+                            
+                            trans = new TTlsSocketClientTransport(host, port, 0, cert, 
+                                (sender, certificate, chain, errors) => true,
+                                null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12);
                         }
                         else
                         {
@@ -184,7 +224,7 @@
         private class ClientTest
         {
             private readonly TClientTransport transport;
-            private readonly ThriftAsync.Test.ThriftTest.Client client;
+            private readonly ThriftTest.Client client;
             private readonly int numIterations;
             private bool done;
 
@@ -193,7 +233,7 @@
             public ClientTest(TestParams param)
             {
                 transport = param.CreateTransport();
-                client = new ThriftAsync.Test.ThriftTest.Client(param.CreateProtocol(transport));
+                client = new ThriftTest.Client(param.CreateProtocol(transport));
                 numIterations = param.numIterations;
             }
 
@@ -224,6 +264,14 @@
                         Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
                         continue;
                     }
+                    catch (Exception ex)
+                    {
+                        Console.WriteLine("*** FAILED ***");
+                        Console.WriteLine("Connect failed: " + ex.Message);
+                        ReturnCode |= ErrorUnknown;
+                        Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+                        continue;
+                    }
 
                     try
                     {
@@ -285,17 +333,14 @@
                 var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray();
 
                 //issue tests on separate threads simultaneously
-                var threads = tests.Select(test => new Thread(test.Execute)).ToArray();
+                var threads = tests.Select(test => new Task(test.Execute)).ToArray();
                 var start = DateTime.Now;
                 foreach (var t in threads)
                 {
                     t.Start();
                 }
 
-                foreach (var t in threads)
-                {
-                    t.Join();
-                }
+                Task.WaitAll(threads);
 
                 Console.WriteLine("Total time: " + (DateTime.Now - start));
                 Console.WriteLine();
@@ -351,7 +396,7 @@
             return retval;
         }
 
-        public static async Task<int> ExecuteClientTestAsync(ThriftAsync.Test.ThriftTest.Client client)
+        public static async Task<int> ExecuteClientTestAsync(ThriftTest.Client client)
         {
             var token = CancellationToken.None;
             var returnCode = 0;
diff --git a/test/netcore/Makefile.am b/test/netcore/Makefile.am
index e029a24..376ffb7 100644
--- a/test/netcore/Makefile.am
+++ b/test/netcore/Makefile.am
@@ -19,41 +19,23 @@
 
 SUBDIRS = . 
 
-THRIFT = $(top_builddir)/compiler/cpp/thrift
-
-GENDIR = ThriftTest/gen-netcore
-
-THRIFTCODE = \
-			ThriftTest/TestClient.cs \
-			ThriftTest/TestServer.cs \
-			ThriftTest/Properties/AssemblyInfo.cs \
-			ThriftTest/Program.cs 
-
-all-local: \
-	ThriftTest/stage/ThriftTest.dll
-
-ThriftTest/stage/ThriftTest.dll: $(THRIFTCODE)
-	$(MKDIR_P) $(GENDIR)
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/test/ThriftTest.thrift
-	$(DOTNETCORE) --info
-	$(DOTNETCORE) restore
+all-local:
 	$(DOTNETCORE) build
 
-precross: \
-	ThriftTest/stage/ThriftTest.dll
+precross:
+	$(DOTNETCORE) build
 
 clean-local:
-	$(RM) ThriftTest.exe
-	$(RM) -r $(GENDIR)
-	$(RM) -r ThriftTest/bin
-	$(RM) -r ThriftTest/obj
+	$(RM) -r Client/bin
+	$(RM) -r Server/bin
+	$(RM) -r Client/obj
+	$(RM) -r Server/obj
+	$(RM) -r ThriftTest/ThriftTest
 
 EXTRA_DIST = \
-			 $(THRIFTCODE) \
-			 ThriftTest.sln \
-			 ThriftTest/ThriftTest.csproj \
-			 ThriftTest/Properties/launchSettings.json \
-			 build.cmd \
-			 build.sh \
-			 README.md
-			 
+	Client \
+	README.md \
+	Server \
+	ThriftTest.sln \
+	build.cmd \
+	build.sh
diff --git a/test/netcore/README.md b/test/netcore/README.md
index 05eb0e2..ed728d1 100644
--- a/test/netcore/README.md
+++ b/test/netcore/README.md
@@ -9,7 +9,10 @@
 - NET Core Standard 1.6 (SDK 2.0.0)
 
 # How to build on Windows
+- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable
 - Open ThriftTest.sln in Visual Studio and build
+or 
+- Build with scripts
 
 # How to build on Unix
 - Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image
diff --git a/test/netcore/Server/.gitignore b/test/netcore/Server/.gitignore
new file mode 100644
index 0000000..67d5510
--- /dev/null
+++ b/test/netcore/Server/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/ThriftTest
diff --git a/test/netcore/ThriftTest/Program.cs b/test/netcore/Server/Program.cs
similarity index 82%
copy from test/netcore/ThriftTest/Program.cs
copy to test/netcore/Server/Program.cs
index 94ed9d9..e647e5b 100644
--- a/test/netcore/ThriftTest/Program.cs
+++ b/test/netcore/Server/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -17,9 +17,9 @@
 
 using System;
 using System.Collections.Generic;
-using Test;
+using ThriftTest;
 
-namespace ThriftTest
+namespace Server
 {
     public class Program
     {
@@ -46,8 +46,6 @@
             // run whatever mode is choosen
             switch(firstArg)
             {
-                case "client":
-                    return TestClient.Execute(subArgs);
                 case "server":
                     return TestServer.Execute(subArgs);
                 case "--help":
@@ -62,13 +60,11 @@
         private static void PrintHelp()
         {
             Console.WriteLine("Usage:");
-            Console.WriteLine("  ThriftTest  server  [options]'");
-            Console.WriteLine("  ThriftTest  client  [options]'");
-            Console.WriteLine("  ThriftTest  --help");
+            Console.WriteLine("  Server  server  [options]'");
+            Console.WriteLine("  Server  --help");
             Console.WriteLine("");
 
             TestServer.PrintOptionsHelp();
-            TestClient.PrintOptionsHelp();
         }
     }
 }
diff --git a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs b/test/netcore/Server/Properties/AssemblyInfo.cs
similarity index 97%
rename from test/netcore/ThriftTest/Properties/AssemblyInfo.cs
rename to test/netcore/Server/Properties/AssemblyInfo.cs
index efc9e33..265495c 100644
--- a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs
+++ b/test/netcore/Server/Properties/AssemblyInfo.cs
@@ -22,7 +22,7 @@
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 
-[assembly: AssemblyTitle("ThriftTest")]
+[assembly: AssemblyTitle("Server")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("The Apache Software Foundation")]
diff --git a/test/netcore/Server/Server.csproj b/test/netcore/Server/Server.csproj
new file mode 100644
index 0000000..2f9b4b1
--- /dev/null
+++ b/test/netcore/Server/Server.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Server</AssemblyName>
+    <PackageId>Server</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
+    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
+    <PackageReference Include="System.Threading" Version="[4.3,)" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="&quot;$(PathToThrift)&quot; -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/test/netcore/ThriftTest/TestServer.cs b/test/netcore/Server/TestServer.cs
similarity index 89%
rename from test/netcore/ThriftTest/TestServer.cs
rename to test/netcore/Server/TestServer.cs
index aa25c91..bfd3335 100644
--- a/test/netcore/ThriftTest/TestServer.cs
+++ b/test/netcore/Server/TestServer.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -17,13 +17,14 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
 using System.Security.Authentication;
 using System.Security.Cryptography.X509Certificates;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
-using ThriftAsync.Test;
 using Thrift;
 using Thrift.Collections;
 using Thrift.Protocols;
@@ -31,7 +32,7 @@
 using Thrift.Transports;
 using Thrift.Transports.Server;
 
-namespace Test
+namespace ThriftTest
 {
     internal class ServerParam
     {
@@ -93,7 +94,7 @@
                 }
                 else
                 {
-                    throw new ArgumentException(args[i]);
+                    //throw new ArgumentException(args[i]);
                 }
             }
 
@@ -132,9 +133,9 @@
                 callCount++;
                 return Task.CompletedTask;
             }
-        };
+        }
 
-        public class TestHandlerAsync : ThriftAsync.Test.ThriftTest.IAsync
+        public class TestHandlerAsync : ThriftTest.IAsync
         {
             public TBaseServer server { get; set; }
             private int handlerID;
@@ -439,20 +440,13 @@
             public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken)
             {
                 logger.Invoke("testOneway({0}), sleeping...", secondsToSleep);
-                Thread.Sleep(secondsToSleep * 1000);
+                Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult();
                 logger.Invoke("testOneway finished");
 
                 return Task.CompletedTask;
             }
         }
 
-
-        private enum ProcessorFactoryType
-        {
-            TSingletonProcessorFactory,
-            TPrototypeProcessorFactory,
-        }
-
         internal static void PrintOptionsHelp()
         {
             Console.WriteLine("Server options:");
@@ -466,8 +460,41 @@
             Console.WriteLine();
         }
 
+        private static X509Certificate2 GetServerCert()
+        {
+            var serverCertName = "server.p12";
+            var possiblePaths = new List<string>
+            {
+                "../../../keys/",
+                "../../keys/",
+                "../keys/",
+                "keys/",
+            };
+                        
+            string existingPath = null;
+            foreach (var possiblePath in possiblePaths)
+            {
+                var path = Path.GetFullPath(possiblePath + serverCertName);
+                if (File.Exists(path))
+                {
+                    existingPath = path;
+                    break;
+                }
+            }
+                        
+            if (string.IsNullOrEmpty(existingPath))
+            {
+                throw new FileNotFoundException($"Cannot find file: {serverCertName}");
+            }
+                                    
+            var cert = new X509Certificate2(existingPath, "thrift");
+                        
+            return cert;
+        }
+
         public static int Execute(List<string> args)
         {
+            var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug();
             var logger = new LoggerFactory().CreateLogger("Test");
 
             try
@@ -493,16 +520,28 @@
                 {
                     trans = new TNamedPipeServerTransport(param.pipe);
                 }
+//                else if (param.useFramed)
+//                {
+//                    trans = new TServerFramedTransport(param.port);
+//                }
                 else
                 {
                     if (param.useEncryption)
                     {
-                        var certPath = "../../keys/server.p12";
-                        trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, new X509Certificate2(certPath, "thrift"), null, null, SslProtocols.Tls);
+                        var cert = GetServerCert();
+                        
+                        if (cert == null || !cert.HasPrivateKey)
+                        {
+                            throw new InvalidOperationException("Certificate doesn't contain private key");
+                        }
+                        
+                        trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, 
+                            (sender, certificate, chain, errors) => true, 
+                            null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12);
                     }
                     else
                     {
-                        trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets);
+                        trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed);
                     }
                 }
 
@@ -518,15 +557,10 @@
 
                 // Processor
                 var testHandler = new TestHandlerAsync();
-                var testProcessor = new ThriftAsync.Test.ThriftTest.AsyncProcessor(testHandler);
+                var testProcessor = new ThriftTest.AsyncProcessor(testHandler);
                 processorFactory = new SingletonTProcessorFactory(testProcessor);
 
-
-                TTransportFactory transFactory;
-                if (param.useFramed)
-                    throw new NotImplementedException("framed"); // transFactory = new TFramedTransport.Factory();
-                else
-                    transFactory = new TTransportFactory();
+                TTransportFactory transFactory = new TTransportFactory(); 
 
                 TBaseServer serverEngine = new AsyncBaseServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger);
 
diff --git a/test/netcore/ThriftTest.sln b/test/netcore/ThriftTest.sln
index c3f194b..2ab241a 100644
--- a/test/netcore/ThriftTest.sln
+++ b/test/netcore/ThriftTest.sln
@@ -1,11 +1,13 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.26730.12
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThriftTest", "ThriftTest\ThriftTest.csproj", "{DDED46FF-F359-47B4-BA7E-9B70F216BD44}"
-EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -16,18 +18,6 @@
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x64.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x86.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x64.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x64.Build.0 = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x86.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x86.Build.0 = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -40,6 +30,30 @@
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/test/netcore/ThriftTest/Properties/launchSettings.json b/test/netcore/ThriftTest/Properties/launchSettings.json
deleted file mode 100644
index ddafa79..0000000
--- a/test/netcore/ThriftTest/Properties/launchSettings.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "profiles": {
-    "ThriftTest": {
-      "commandName": "Project"
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/netcore/ThriftTest/ThriftTest.csproj b/test/netcore/ThriftTest/ThriftTest.csproj
deleted file mode 100644
index 6647101..0000000
--- a/test/netcore/ThriftTest/ThriftTest.csproj
+++ /dev/null
@@ -1,27 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
-    <AssemblyName>ThriftTest</AssemblyName>
-    <PackageId>ThriftTest</PackageId>
-    <OutputType>Exe</OutputType>
-    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
-    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
-    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
-    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
-    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
-    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
-    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
-    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
-    <PackageReference Include="System.Threading" Version="[4.3,)" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
-  </ItemGroup>
-
-</Project>
diff --git a/test/netcore/build.cmd b/test/netcore/build.cmd
index e971799..9b84ef2 100644
--- a/test/netcore/build.cmd
+++ b/test/netcore/build.cmd
@@ -19,12 +19,7 @@
 rem  */
 setlocal
 
-cd Interfaces
-thrift  -gen netcore:wcf   -r  ..\..\tutorial.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
 
 :eof
diff --git a/test/netcore/build.sh b/test/netcore/build.sh
index 626635c..c97e310 100755
--- a/test/netcore/build.sh
+++ b/test/netcore/build.sh
@@ -22,10 +22,5 @@
 #exit if any command fails
 set -e
 
-cd ThriftTest
-../../../compiler/cpp/thrift  -gen netcore:wcf   -r  ../../ThriftTest.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
diff --git a/test/perl/TestClient.pl b/test/perl/TestClient.pl
index 990274c..96e3bec 100755
--- a/test/perl/TestClient.pl
+++ b/test/perl/TestClient.pl
@@ -45,7 +45,7 @@
 $|++;
 
 sub usage {
-    print <<EOF;
+    print <<"EOF";
 Usage: $0 [OPTIONS]
 
 Options:                          (default)
@@ -91,20 +91,24 @@
 }
 
 my $socket = undef;
-if ($opts{"domain-socket"}) {
-    $socket = new Thrift::UnixSocket($opts{"domain-socket"});
-} elsif ($opts{ssl}) {
-  $socket = new Thrift::SSLSocket(\%opts);
-} else {
-  $socket = new Thrift::Socket($opts{host}, $opts{port});
+if ($opts{'domain-socket'}) {
+    $socket = Thrift::UnixSocket->new($opts{'domain-socket'});
+}
+elsif ($opts{ssl}) {
+  $socket = Thrift::SSLSocket->new(\%opts);
+}
+else {
+  $socket = Thrift::Socket->new($opts{host}, $opts{port});
 }
 
 my $transport;
 if ($opts{transport} eq 'buffered') {
-    $transport = new Thrift::BufferedTransport($socket, 1024, 1024);
-} elsif ($opts{transport} eq 'framed') {
-    $transport = new Thrift::FramedTransport($socket);
-} else {
+    $transport = Thrift::BufferedTransport->new($socket, 1024, 1024);
+}
+elsif ($opts{transport} eq 'framed') {
+    $transport = Thrift::FramedTransport->new($socket);
+}
+else {
     usage();
     exit 1;
 }
@@ -112,20 +116,21 @@
 my $protocol;
 my $protocol2;
 if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') {
-    $protocol = new Thrift::BinaryProtocol($transport);
-} else {
+    $protocol = Thrift::BinaryProtocol->new($transport);
+}
+else {
     usage();
     exit 1;
 }
 
 my $secondService = undef;
 if (index($opts{protocol}, 'multi') == 0) {
-  $protocol2 = new Thrift::MultiplexedProtocol($protocol, "SecondService");
-  $protocol = new Thrift::MultiplexedProtocol($protocol, "ThriftTest");
-  $secondService = new ThriftTest::SecondServiceClient($protocol2);
+  $protocol2     = Thrift::MultiplexedProtocol->new($protocol, 'SecondService');
+  $protocol      = Thrift::MultiplexedProtocol->new($protocol, 'ThriftTest');
+  $secondService = ThriftTest::SecondServiceClient->new($protocol2);
 }
 
-my $testClient = new ThriftTest::ThriftTestClient($protocol);
+my $testClient = ThriftTest::ThriftTestClient->new($protocol);
 
 eval {
   $transport->open();
@@ -146,52 +151,52 @@
 #
 # VOID TEST
 #
-print("testVoid()");
+print('testVoid()');
 $testClient->testVoid();
 print(" = void\n");
 
 #
 # STRING TEST
 #
-print("testString(\"Test\")");
-my $s = $testClient->testString("Test");
-print(" = \"$s\"\n");
+print('testString("Test")');
+my $s = $testClient->testString('Test');
+print(qq| = "$s"\n|);
 exit(ERR_BASETYPES) if ($s ne 'Test');
 
 #
 # MULTIPLEXED TEST
 #
 if (index($opts{protocol}, 'multi') == 0) {
-    print("secondtestString(\"Test2\")");
-    $s = $secondService->secondtestString("Test2");
-    print(" = \"$s\"\n");
+    print('secondtestString("Test2")');
+    $s = $secondService->secondtestString('Test2');
+    print(qq| = "$s"\n|);
     exit(ERR_PROTOCOL) if ($s ne 'testString("Test2")');
 }
 
 #
 # BOOL TEST
 #
-print("testBool(1)");
+print('testBool(1)');
 my $t = $testClient->testBool(1);
 print(" = $t\n");
 exit(ERR_BASETYPES) if ($t ne 1);
-print("testBool(0)");
+print('testBool(0)');
 my $f = $testClient->testBool(0);
 print(" = $f\n");
-exit(ERR_BASETYPES) if ($f ne "");
+exit(ERR_BASETYPES) if ($f ne q||);
 
 
 #
 # BYTE TEST
 #
-print("testByte(1)");
+print('testByte(1)');
 my $u8 = $testClient->testByte(1);
 print(" = $u8\n");
 
 #
 # I32 TEST
 #
-print("testI32(-1)");
+print('testI32(-1)');
 my $i32 = $testClient->testI32(-1);
 print(" = $i32\n");
 exit(ERR_BASETYPES) if ($i32 ne -1);
@@ -199,7 +204,7 @@
 #
 # I64 TEST
 #
-print("testI64(-34359738368)");
+print('testI64(-34359738368)');
 my $i64 = $testClient->testI64(-34359738368);
 print(" = $i64\n");
 exit(ERR_BASETYPES) if ($i64 ne -34359738368);
@@ -207,7 +212,7 @@
 #
 # DOUBLE TEST
 #
-print("testDouble(-852.234234234)");
+print('testDouble(-852.234234234)');
 my $dub = $testClient->testDouble(-852.234234234);
 print(" = $dub\n");
 exit(ERR_BASETYPES) if ($dub ne -852.234234234);
@@ -220,33 +225,33 @@
 #
 # STRUCT TEST
 #
-print("testStruct({\"Zero\", 1, -3, -5})");
-my $out = new ThriftTest::Xtruct();
-$out->string_thing("Zero");
+print('testStruct({"Zero", 1, -3, -5})');
+my $out = ThriftTest::Xtruct->new();
+$out->string_thing('Zero');
 $out->byte_thing(1);
 $out->i32_thing(-3);
 $out->i64_thing(-5);
 my $in = $testClient->testStruct($out);
-print(" = {\"".$in->string_thing."\", ".
-        $in->byte_thing.", ".
-        $in->i32_thing.", ".
+print(' = {"'.$in->string_thing.'", '.
+        $in->byte_thing.', '.
+        $in->i32_thing.', '.
         $in->i64_thing."}\n");
 
 #
 # NESTED STRUCT TEST
 #
-print("testNest({1, {\"Zero\", 1, -3, -5}, 5}");
-my $out2 = new ThriftTest::Xtruct2();
+print('testNest({1, {"Zero", 1, -3, -5}, 5}');
+my $out2 = ThriftTest::Xtruct2->new();
 $out2->byte_thing(1);
 $out2->struct_thing($out);
 $out2->i32_thing(5);
 my $in2 = $testClient->testNest($out2);
 $in = $in2->struct_thing;
-print(" = {".$in2->byte_thing.", {\"".
-      $in->string_thing."\", ".
-      $in->byte_thing.", ".
-      $in->i32_thing.", ".
-      $in->i64_thing."}, ".
+print(' = {'.$in2->byte_thing.', {"'.
+      $in->string_thing.'", '.
+      $in->byte_thing.', '.
+      $in->i32_thing.', '.
+      $in->i64_thing.'}, '.
       $in2->i32_thing."}\n");
 
 #
@@ -256,28 +261,30 @@
 for (my $i = 0; $i < 5; ++$i) {
   $mapout->{$i} = $i-10;
 }
-print("testMap({");
+print('testMap({');
 my $first = 1;
 while( my($key,$val) = each %$mapout) {
     if ($first) {
         $first = 0;
-    } else {
-        print(", ");
+    }
+    else {
+        print(', ');
     }
     print("$key => $val");
 }
-print("})");
+print('})');
 
 
 my $mapin = $testClient->testMap($mapout);
-print(" = {");
+print(' = {');
 
 $first = 1;
 while( my($key,$val) = each %$mapin){
     if ($first) {
         $first = 0;
-    } else {
-        print(", ");
+    }
+    else {
+        print(', ');
     }
     print("$key => $val");
 }
@@ -291,11 +298,11 @@
     push(@$setout, $i);
 }
 
-print("testSet({".join(",",@$setout)."})");
+print('testSet({'.join(',',@$setout).'})');
 
 my $setin = $testClient->testSet($setout);
 
-print(" = {".join(",",@$setout)."}\n");
+print(' = {'.join(',',@$setout)."}\n");
 
 #
 # LIST TEST
@@ -305,111 +312,111 @@
     push(@$listout, $i);
 }
 
-print("testList({".join(",",@$listout)."})");
+print('testList({'.join(',',@$listout).'})');
 
 my $listin = $testClient->testList($listout);
 
-print(" = {".join(",",@$listin)."}\n");
+print(' = {'.join(',',@$listin)."}\n");
 
 #
 # ENUM TEST
 #
-print("testEnum(ONE)");
+print('testEnum(ONE)');
 my $ret = $testClient->testEnum(ThriftTest::Numberz::ONE);
 print(" = $ret\n");
 
-print("testEnum(TWO)");
+print('testEnum(TWO)');
 $ret = $testClient->testEnum(ThriftTest::Numberz::TWO);
 print(" = $ret\n");
 
-print("testEnum(THREE)");
+print('testEnum(THREE)');
 $ret = $testClient->testEnum(ThriftTest::Numberz::THREE);
 print(" = $ret\n");
 
-print("testEnum(FIVE)");
+print('testEnum(FIVE)');
 $ret = $testClient->testEnum(ThriftTest::Numberz::FIVE);
 print(" = $ret\n");
 
-print("testEnum(EIGHT)");
+print('testEnum(EIGHT)');
 $ret = $testClient->testEnum(ThriftTest::Numberz::EIGHT);
 print(" = $ret\n");
 
 #
 # TYPEDEF TEST
 #
-print("testTypedef(309858235082523)");
+print('testTypedef(309858235082523)');
 my $uid = $testClient->testTypedef(309858235082523);
 print(" = $uid\n");
 
 #
 # NESTED MAP TEST
 #
-print("testMapMap(1)");
+print('testMapMap(1)');
 my $mm = $testClient->testMapMap(1);
-print(" = {");
+print(' = {');
 while( my ($key,$val) = each %$mm) {
     print("$key => {");
     while( my($k2,$v2) = each %$val) {
         print("$k2 => $v2, ");
     }
-    print("}, ");
+    print('}, ');
 }
 print("}\n");
 
 #
 # INSANITY TEST
 #
-my $insane = new ThriftTest::Insanity();
+my $insane = ThriftTest::Insanity->new();
 $insane->{userMap}->{ThriftTest::Numberz::FIVE} = 5000;
-my $truck = new ThriftTest::Xtruct();
-$truck->string_thing("Hello2");
+my $truck = ThriftTest::Xtruct->new();
+$truck->string_thing('Hello2');
 $truck->byte_thing(2);
 $truck->i32_thing(2);
 $truck->i64_thing(2);
-my $truck2 = new ThriftTest::Xtruct();
-$truck2->string_thing("Goodbye4");
+my $truck2 = ThriftTest::Xtruct->new();
+$truck2->string_thing('Goodbye4');
 $truck2->byte_thing(4);
 $truck2->i32_thing(4);
 $truck2->i64_thing(4);
 push(@{$insane->{xtructs}}, $truck);
 push(@{$insane->{xtructs}}, $truck2);
 
-print("testInsanity()");
+print('testInsanity()');
 my $whoa = $testClient->testInsanity($insane);
-print(" = {");
+print(' = {');
 while( my ($key,$val) = each %$whoa) {
     print("$key => {");
     while( my($k2,$v2) = each %$val) {
         print("$k2 => {");
         my $userMap = $v2->{userMap};
-        print("{");
-        if (ref($userMap) eq "HASH") {
+        print('{');
+        if (ref($userMap) eq 'HASH') {
             while( my($k3,$v3) = each %$userMap) {
                 print("$k3 => $v3, ");
             }
         }
-        print("}, ");
+        print('}, ');
 
         my $xtructs = $v2->{xtructs};
-        print("{");
-        if (ref($xtructs) eq "ARRAY") {
+        print('{');
+        if (ref($xtructs) eq 'ARRAY') {
             foreach my $x (@$xtructs) {
-                print("{\"".$x->{string_thing}."\", ".
-                      $x->{byte_thing}.", ".$x->{i32_thing}.", ".$x->{i64_thing}."}, ");
+                print('{"'.$x->{string_thing}.'", '.
+                      $x->{byte_thing}.', '.$x->{i32_thing}.', '.$x->{i64_thing}.'}, ');
             }
         }
-        print("}");
+        print('}');
 
-        print("}, ");
+        print('}, ');
     }
-    print("}, ");
+    print('}, ');
 }
 print("}\n");
 
 #
 # EXCEPTION TEST
 #
-print("testException('Xception')");
+print(q|testException('Xception')|);
 eval {
     $testClient->testException('Xception');
     print("  void\nFAILURE\n");
@@ -422,7 +429,7 @@
 # Normal tests done.
 #
 my $stop = gettimeofday();
-my $elp  = sprintf("%d",1000*($stop - $start), 0);
+my $elp  = sprintf('%d',1000*($stop - $start), 0);
 print("Total time: $elp ms\n");
 
 #
diff --git a/test/perl/TestServer.pl b/test/perl/TestServer.pl
index 7d8f929..d2b9a38 100644
--- a/test/perl/TestServer.pl
+++ b/test/perl/TestServer.pl
@@ -26,6 +26,8 @@
 use Getopt::Long qw(GetOptions);
 use Time::HiRes qw(gettimeofday);
 
+$SIG{INT} = \&sigint_handler;
+
 use lib '../../lib/perl/lib';
 use lib 'gen-perl';
 
@@ -46,7 +48,7 @@
 $|++;
 
 sub usage {
-    print <<EOF;
+    print <<"EOF";
 Usage: $0 [OPTIONS]
 
 Options:                          (default)
@@ -97,55 +99,67 @@
     exit 1;
 }
 
-my $handler = new ThriftTestHandler();
-my $handler2 = new SecondServiceHandler();
-my $processor = new ThriftTest::ThriftTestProcessor($handler);
-my $processor2 = new ThriftTest::SecondServiceProcessor($handler2);
+my $handler    = ThriftTestHandler->new();
+my $handler2   = SecondServiceHandler->new();
+my $processor  = ThriftTest::ThriftTestProcessor->new($handler);
+my $processor2 = ThriftTest::SecondServiceProcessor->new($handler2);
+
 my $serversocket;
-if ($opts{"domain-socket"}) {
-    unlink($opts{"domain-socket"});
-    $serversocket = new Thrift::UnixServerSocket($opts{"domain-socket"});
-} elsif ($opts{ssl}) {
-    $serversocket = new Thrift::SSLServerSocket(\%opts);
-} else {
-    $serversocket = new Thrift::ServerSocket(\%opts);
+if ($opts{'domain-socket'}) {
+    unlink($opts{'domain-socket'});
+    $serversocket = Thrift::UnixServerSocket->new($opts{'domain-socket'});
+}
+elsif ($opts{ssl}) {
+    $serversocket = Thrift::SSLServerSocket->new(\%opts);
+}
+else {
+    $serversocket = Thrift::ServerSocket->new(\%opts);
 }
 my $transport;
 if ($opts{transport} eq 'buffered') {
-    $transport = new Thrift::BufferedTransportFactory();
-} elsif ($opts{transport} eq 'framed') {
-    $transport = new Thrift::FramedTransportFactory();
-} else {
+    $transport = Thrift::BufferedTransportFactory->new();
+}
+elsif ($opts{transport} eq 'framed') {
+    $transport = Thrift::FramedTransportFactory->new();
+}
+else {
     usage();
     exit 1;
 }
 my $protocol;
 if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') {
-    $protocol = new Thrift::BinaryProtocolFactory();
-} else {
+    $protocol = Thrift::BinaryProtocolFactory->new();
+}
+else {
     usage();
     exit 1;
 }
 
 if (index($opts{protocol}, 'multi') == 0) {
-  my $newProcessor = new Thrift::MultiplexedProcessor($protocol);
+  my $newProcessor = Thrift::MultiplexedProcessor->new($protocol);
   $newProcessor->defaultProcessor($processor);
-  $newProcessor->registerProcessor("ThriftTest", $processor);
-  $newProcessor->registerProcessor("SecondService", $processor2);
+  $newProcessor->registerProcessor('ThriftTest', $processor);
+  $newProcessor->registerProcessor('SecondService', $processor2);
   $processor = $newProcessor;
 }
 
 my $ssltag = '';
 if ($opts{ssl}) {
-    $ssltag = "(SSL)";
+    $ssltag = '(SSL)';
 }
 my $listening_on = "$opts{port} $ssltag";
-if ($opts{"domain-socket"}) {
-    $listening_on = $opts{"domain-socket"};
+if ($opts{'domain-socket'}) {
+    $listening_on = $opts{'domain-socket'};
 }
-my $server = new Thrift::SimpleServer($processor, $serversocket, $transport, $protocol);
-print "Starting \"simple\" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n";
+my $server = Thrift::SimpleServer->new($processor, $serversocket, $transport, $protocol);
+print qq|Starting "simple" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n|;
 $server->serve();
+print "done.\n";
+
+sub sigint_handler {
+  print "received SIGINT, stopping...\n";
+  $server->stop();
+}
 
 ###
 ### Test server implementation
@@ -161,70 +175,67 @@
     return bless($self, $classname);
 }
 
-sub testVoid() {
+sub testVoid {
   print("testVoid()\n");
 }
 
-sub testString() {
+sub testString {
   my $self = shift;
   my $thing = shift;
   print("testString($thing)\n");
   return $thing;
 }
 
-sub testBool() {
+sub testBool {
   my $self = shift;
   my $thing = shift;
-  my $str = $thing ? "true" : "false";
+  my $str = $thing ? 'true' : 'false';
   print("testBool($str)\n");
   return $thing;
 }
 
-sub testByte() {
+sub testByte {
   my $self = shift;
   my $thing = shift;
   print("testByte($thing)\n");
   return $thing;
 }
 
-sub testI32() {
+sub testI32 {
   my $self = shift;
   my $thing = shift;
   print("testI32($thing)\n");
   return $thing;
 }
 
-sub testI64() {
+sub testI64 {
   my $self = shift;
   my $thing = shift;
   print("testI64($thing)\n");
   return $thing;
 }
 
-sub testDouble() {
+sub testDouble {
   my $self = shift;
   my $thing = shift;
   print("testDouble($thing)\n");
   return $thing;
 }
 
-sub testBinary() {
+sub testBinary {
     my $self = shift;
     my $thing = shift;
     my @bytes = split //, $thing;
-    print("testBinary(");
-    foreach (@bytes)
-    {
-        printf "%02lx", ord $_;
-    }
-    print(")\n");
+    print 'testBinary(';
+    printf( '%02lx', ord $_ ) foreach (@bytes);
+    print ")\n";
     return $thing;
 }
 
-sub testStruct() {
+sub testStruct {
   my $self = shift;
   my $thing = shift;
-  printf("testStruct({\"%s\", %d, %d, %lld})\n",
+  printf(qq|testStruct({"%s", %d, %d, %lld})\n|,
            $thing->{string_thing},
            $thing->{byte_thing},
            $thing->{i32_thing},
@@ -232,11 +243,11 @@
   return $thing;
 }
 
-sub testNest() {
+sub testNest {
   my $self = shift;
   my $nest = shift;
   my $thing = $nest->{struct_thing};
-  printf("testNest({%d, {\"%s\", %d, %d, %lld}, %d})\n",
+  printf(qq|testNest({%d, {"%s", %d, %d, %lld}, %d})\n|,
            $nest->{byte_thing},
            $thing->{string_thing},
            $thing->{byte_thing},
@@ -246,92 +257,58 @@
   return $nest;
 }
 
-sub testMap() {
+sub testMap {
   my $self = shift;
   my $thing = shift;
-  print("testMap({");
-  my $first = 1;
-  foreach my $key (keys %$thing) {
-    if ($first) {
-        $first = 0;
-    } else {
-        print(", ");
-    }
-    print("$key => $thing->{$key}");
-  }
-  print("})\n");
+  printf "testMap({%s})\n",
+    join( ', ',
+          map { $_ . ' => ' . $thing->{$_} }
+          sort keys %$thing
+    );
   return $thing;
 }
 
-sub testStringMap() {
+sub testStringMap {
   my $self = shift;
   my $thing = shift;
-  print("testStringMap({");
-  my $first = 1;
-  foreach my $key (keys %$thing) {
-    if ($first) {
-        $first = 0;
-    } else {
-        print(", ");
-    }
-    print("$key => $thing->{$key}");
-  }
-  print("})\n");
+  printf "testStringMap({%s})\n",
+    join( ', ',
+          map { $_ . ' => ' . $thing->{$_} }
+          sort keys %$thing
+    );
   return $thing;
 }
 
-sub testSet() {
+sub testSet {
   my $self = shift;
   my $thing = shift;
-  my @arr;
-  my $result = \@arr;
-  print("testSet({");
-  my $first = 1;
-  foreach my $key (keys %$thing) {
-    if ($first) {
-        $first = 0;
-    } else {
-        print(", ");
-    }
-    print("$key");
-    push(@arr, $key);
-  }
-  print("})\n");
-  return $result;
+  my @result = sort keys %$thing;
+  printf "testSet({%s})\n", join(', ', @result );
+  return \@result;
 }
 
-sub testList() {
+sub testList {
   my $self = shift;
   my $thing = shift;
-  print("testList({");
-  my $first = 1;
-  foreach my $key (@$thing) {
-    if ($first) {
-        $first = 0;
-    } else {
-        print(", ");
-    }
-    print("$key");
-  }
-  print("})\n");
+  print "testList({%s})\n", join(', ', @$thing);
   return $thing;
 }
 
-sub testEnum() {
+sub testEnum {
   my $self = shift;
   my $thing = shift;
-  print("testEnum($thing)\n");
+  print "testEnum($thing)\n";
   return $thing;
 }
 
-sub testTypedef() {
+sub testTypedef {
   my $self = shift;
   my $thing = shift;
   print("testTypedef($thing)\n");
   return $thing;
 }
 
-sub testMapMap() {
+sub testMapMap {
   my $self = shift;
   my $hello = shift;
 
@@ -340,25 +317,25 @@
   return $result;
 }
 
-sub testInsanity() {
+sub testInsanity {
   my $self = shift;
   my $argument = shift;
   print("testInsanity()\n");
 
-  my $hello = new ThriftTest::Xtruct({string_thing => "Hello2", byte_thing => 2, i32_thing => 2, i64_thing => 2});
+  my $hello = ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => 2, i32_thing => 2, i64_thing => 2});
   my @hellos;
   push(@hellos, $hello);
-  my $goodbye = new ThriftTest::Xtruct({string_thing => "Goodbye4", byte_thing => 4, i32_thing => 4, i64_thing => 4});
+  my $goodbye = ThriftTest::Xtruct->new({string_thing => 'Goodbye4', byte_thing => 4, i32_thing => 4, i64_thing => 4});
   my @goodbyes;
   push(@goodbyes, $goodbye);
-  my $crazy = new ThriftTest::Insanity({userMap => { ThriftTest::Numberz::EIGHT => 8 }, xtructs => \@goodbyes});
-  my $loony = new ThriftTest::Insanity();
+  my $crazy = ThriftTest::Insanity->new({userMap => { ThriftTest::Numberz::EIGHT => 8 }, xtructs => \@goodbyes});
+  my $loony = ThriftTest::Insanity->new();
   my $result = { 1 => { ThriftTest::Numberz::TWO => $argument, ThriftTest::Numberz::THREE => $argument },
                  2 => { ThriftTest::Numberz::SIX => $loony } };
   return $result;
 }
 
-sub testMulti() {
+sub testMulti {
   my $self = shift;
   my $arg0 = shift;
   my $arg1 = shift;
@@ -368,39 +345,43 @@
   my $arg5 = shift;
 
   print("testMulti()\n");
-  return new ThriftTest::Xtruct({string_thing => "Hello2", byte_thing => $arg0, i32_thing => $arg1, i64_thing => $arg2});
+  return ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => $arg0, i32_thing => $arg1, i64_thing => $arg2});
 }
 
-sub testException() {
+sub testException {
   my $self = shift;
   my $arg = shift;
   print("testException($arg)\n");
-  if ($arg eq "Xception") {
-    die new ThriftTest::Xception({errorCode => 1001, message => $arg});
-  } elsif ($arg eq "TException") {
-    die "astring"; # all unhandled exceptions become TExceptions
-  } else {
-    return new ThriftTest::Xtruct({string_thing => $arg});
+  if ($arg eq 'Xception') {
+      die ThriftTest::Xception->new({errorCode => 1001, message => $arg});
+  }
+  elsif ($arg eq 'TException') {
+      die 'astring'; # all unhandled exceptions become TExceptions
+  }
+  else {
+      return ThriftTest::Xtruct->new({string_thing => $arg});
   }
 }
 
-sub testMultiException() {
+sub testMultiException {
   my $self = shift;
   my $arg0 = shift;
   my $arg1 = shift;
 
   printf("testMultiException(%s, %s)\n", $arg0, $arg1);
-  if ($arg0 eq "Xception") {
-    die new ThriftTest::Xception({errorCode => 1001, message => "This is an Xception"});
-  } elsif ($arg0 eq "Xception2") {
-    my $struct_thing = new ThriftTest::Xtruct({string_thing => "This is an Xception2"});
-    die new ThriftTest::Xception2({errorCode => 2002, struct_thing => $struct_thing});
-  } else {
-    return new ThriftTest::Xtruct({string_thing => $arg1});
+  if ($arg0 eq 'Xception') {
+    die ThriftTest::Xception->new({errorCode => 1001, message => 'This is an Xception'});
+  }
+  elsif ($arg0 eq 'Xception2') {
+    my $struct_thing = ThriftTest::Xtruct->new({string_thing => 'This is an Xception2'});
+    die ThriftTest::Xception2->new({errorCode => 2002, struct_thing => $struct_thing});
+  }
+  else {
+    return ThriftTest::Xtruct->new({string_thing => $arg1});
   }
 }
 
-sub testOneway() {
+sub testOneway {
   my $self = shift;
   my $num = shift;
   print("testOneway($num): received\n");
@@ -420,11 +401,11 @@
     return bless($self, $classname);
 }
 
-sub secondtestString() {
+sub secondtestString {
   my $self = shift;
   my $thing = shift;
   print("testString($thing)\n");
-  return "testString(\"" . $thing . "\")";
+  return qq|testString("$thing")|;
 }
 
 1;
diff --git a/test/php/Makefile.am b/test/php/Makefile.am
index 28357f6..72f7fc5 100755
--- a/test/php/Makefile.am
+++ b/test/php/Makefile.am
@@ -20,8 +20,8 @@
 stubs: ../ThriftTest.thrift
 	$(THRIFT) --gen php ../ThriftTest.thrift
 	$(THRIFT) --gen php:inlined ../ThriftTest.thrift
-	$(MKDIR_P) gen-php-psr4
-	$(THRIFT) -out gen-php-psr4 --gen php:psr4 ../ThriftTest.thrift
+	$(MKDIR_P) gen-php-classmap
+	$(THRIFT) -out gen-php-classmap --gen php ../ThriftTest.thrift
 
 php_ext_dir:
 	mkdir -p php_ext_dir
@@ -33,7 +33,7 @@
 check: stubs php_ext_dir
 
 clean-local:
-	$(RM) -r gen-php gen-phpi gen-php-psr4 php_ext_dir
+	$(RM) -r gen-php gen-phpi gen-php-classmap php_ext_dir
 
 client: stubs php_ext_dir
 	php TestClient.php
diff --git a/test/php/TestPsr4.php b/test/php/TestClassmap.php
similarity index 96%
rename from test/php/TestPsr4.php
rename to test/php/TestClassmap.php
index d30bf1c..6fd1594 100644
--- a/test/php/TestPsr4.php
+++ b/test/php/TestClassmap.php
@@ -18,6 +18,6 @@
  */
 
 <?php
-$GEN_DIR = 'gen-php-psr4';
+$GEN_DIR = 'gen-php-classmap';
 include_once('TestClient.php');
 ?>
diff --git a/test/php/TestClient.php b/test/php/TestClient.php
index 1591027..acd901d 100755
--- a/test/php/TestClient.php
+++ b/test/php/TestClient.php
@@ -2,7 +2,8 @@
 
 namespace test\php;
 
-require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
+/** @var \Composer\Autoload\ClassLoader $loader */
+$loader = require __DIR__ . '/../../vendor/autoload.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
@@ -13,14 +14,14 @@
   $MODE = 'normal';
 }
 
-$loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');
-if ($GEN_DIR === 'gen-php-psr4') {
-  $loader->registerNamespace('ThriftTest', $GEN_DIR);
+
+if ($GEN_DIR == 'gen-php') {
+  $loader->addPsr4('', $GEN_DIR);
 } else {
+  $loader = new ThriftClassLoader();
   $loader->registerDefinition('ThriftTest', $GEN_DIR);
+  $loader->register();
 }
-$loader->register();
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -94,7 +95,7 @@
     $MODE = substr($arg, 12);
   } else if (substr($arg, 0, 11) == '--protocol=') {
     $PROTO = substr($arg, 11);
-  } 
+  }
 }
 
 $hosts = array('localhost');
diff --git a/test/py/Makefile.am b/test/py/Makefile.am
index b3513dd..8296200 100644
--- a/test/py/Makefile.am
+++ b/test/py/Makefile.am
@@ -23,24 +23,31 @@
 thrift_gen =                                    \
         gen-py/ThriftTest/__init__.py           \
         gen-py/DebugProtoTest/__init__.py \
+        gen-py/DoubleConstantsTest/__init__.py \
         gen-py/Recursive/__init__.py \
         gen-py-default/ThriftTest/__init__.py           \
         gen-py-default/DebugProtoTest/__init__.py \
+        gen-py-default/DoubleConstantsTest/__init__.py \
         gen-py-default/Recursive/__init__.py \
         gen-py-slots/ThriftTest/__init__.py           \
         gen-py-slots/DebugProtoTest/__init__.py \
+        gen-py-slots/DoubleConstantsTest/__init__.py \
         gen-py-slots/Recursive/__init__.py \
         gen-py-oldstyle/ThriftTest/__init__.py \
         gen-py-oldstyle/DebugProtoTest/__init__.py \
+        gen-py-oldstyle/DoubleConstantsTest/__init__.py \
         gen-py-oldstyle/Recursive/__init__.py \
         gen-py-no_utf8strings/ThriftTest/__init__.py \
         gen-py-no_utf8strings/DebugProtoTest/__init__.py \
+        gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \
         gen-py-no_utf8strings/Recursive/__init__.py \
         gen-py-dynamic/ThriftTest/__init__.py           \
         gen-py-dynamic/DebugProtoTest/__init__.py \
+        gen-py-dynamic/DoubleConstantsTest/__init__.py \
         gen-py-dynamic/Recursive/__init__.py \
         gen-py-dynamicslots/ThriftTest/__init__.py           \
         gen-py-dynamicslots/DebugProtoTest/__init__.py \
+        gen-py-dynamicslots/DoubleConstantsTest/__init__.py \
         gen-py-dynamicslots/Recursive/__init__.py
 
 
diff --git a/test/py/RunClientServer.py b/test/py/RunClientServer.py
index 7c0f787..56a408e 100755
--- a/test/py/RunClientServer.py
+++ b/test/py/RunClientServer.py
@@ -38,6 +38,7 @@
 SCRIPTS = [
     'FastbinaryTest.py',
     'TestFrozen.py',
+    'TestRenderedDoubleConstants.py',
     'TSimpleJSONProtocolTest.py',
     'SerializationTest.py',
     'TestEof.py',
@@ -55,6 +56,7 @@
     'binary',
     'compact',
     'json',
+    'header',
 ]
 
 
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 1ab8e78..ddcce8d 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -32,8 +32,18 @@
 
 class AbstractTest(unittest.TestCase):
     def setUp(self):
-        if options.http_path:
-            self.transport = THttpClient.THttpClient(options.host, port=options.port, path=options.http_path)
+        if options.trans == 'http':
+            uri = '{0}://{1}:{2}{3}'.format(('https' if options.ssl else 'http'),
+                                            options.host,
+                                            options.port,
+                                            (options.http_path if options.http_path else '/'))
+            if options.ssl:
+                __cafile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "CA.pem")
+                __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.crt")
+                __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.key")
+                self.transport = THttpClient.THttpClient(uri, cafile=__cafile, cert_file=__certfile, key_file=__keyfile)
+            else:
+                self.transport = THttpClient.THttpClient(uri)
         else:
             if options.ssl:
                 from thrift.transport import TSSLSocket
@@ -53,6 +63,9 @@
         self.transport.open()
         protocol = self.get_protocol(self.transport)
         self.client = ThriftTest.Client(protocol)
+        # for multiplexed services:
+        protocol2 = self.get_protocol2(self.transport)
+        self.client2 = SecondService.Client(protocol2) if protocol2 is not None else None
 
     def tearDown(self):
         self.transport.close()
@@ -97,6 +110,11 @@
         self.assertEqual(self.client.testString(s1), s1)
         self.assertEqual(self.client.testString(s2), s2)
 
+    def testMultiplexed(self):
+        if self.client2 is not None:
+            print('testMultiplexed')
+            self.assertEqual(self.client2.secondtestString('foobar'), 'testString("foobar")')
+
     def testBool(self):
         print('testBool')
         self.assertEqual(self.client.testBool(True), True)
@@ -250,44 +268,117 @@
         self.assertEqual(self.client.testString('Python'), 'Python')
 
 
-class NormalBinaryTest(AbstractTest):
+class MultiplexedOptionalTest(AbstractTest):
+    def get_protocol2(self, transport):
+        return None
+
+
+class BinaryTest(MultiplexedOptionalTest):
     def get_protocol(self, transport):
         return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)
 
 
-class CompactTest(AbstractTest):
+class MultiplexedBinaryTest(MultiplexedOptionalTest):
     def get_protocol(self, transport):
-        return TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
+        wrapped_proto = TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest")
+
+    def get_protocol2(self, transport):
+        wrapped_proto = TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
 
 
-class JSONTest(AbstractTest):
-    def get_protocol(self, transport):
-        return TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
-
-
-class AcceleratedBinaryTest(AbstractTest):
+class AcceleratedBinaryTest(MultiplexedOptionalTest):
     def get_protocol(self, transport):
         return TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
 
 
-class AcceleratedCompactTest(AbstractTest):
+class MultiplexedAcceleratedBinaryTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        wrapped_proto = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest")
+
+    def get_protocol2(self, transport):
+        wrapped_proto = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
+
+
+class CompactTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        return TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
+
+
+class MultiplexedCompactTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        wrapped_proto = TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest")
+
+    def get_protocol2(self, transport):
+        wrapped_proto = TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
+
+
+class AcceleratedCompactTest(MultiplexedOptionalTest):
     def get_protocol(self, transport):
         return TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
 
 
+class MultiplexedAcceleratedCompactTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        wrapped_proto = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest")
+
+    def get_protocol2(self, transport):
+        wrapped_proto = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
+
+
+class JSONTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        return TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
+
+
+class MultiplexedJSONTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        wrapped_proto = TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest")
+
+    def get_protocol2(self, transport):
+        wrapped_proto = TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
+        return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService")
+
+
+class HeaderTest(MultiplexedOptionalTest):
+    def get_protocol(self, transport):
+        factory = THeaderProtocol.THeaderProtocolFactory()
+        return factory.getProtocol(transport)
+
+
 def suite():
     suite = unittest.TestSuite()
     loader = unittest.TestLoader()
     if options.proto == 'binary':  # look for --proto on cmdline
-        suite.addTest(loader.loadTestsFromTestCase(NormalBinaryTest))
+        suite.addTest(loader.loadTestsFromTestCase(BinaryTest))
     elif options.proto == 'accel':
         suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest))
-    elif options.proto == 'compact':
-        suite.addTest(loader.loadTestsFromTestCase(CompactTest))
     elif options.proto == 'accelc':
         suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest))
+    elif options.proto == 'compact':
+        suite.addTest(loader.loadTestsFromTestCase(CompactTest))
+    elif options.proto == 'header':
+        suite.addTest(loader.loadTestsFromTestCase(HeaderTest))
     elif options.proto == 'json':
         suite.addTest(loader.loadTestsFromTestCase(JSONTest))
+    elif options.proto == 'multi':
+        suite.addTest(loader.loadTestsFromTestCase(MultiplexedBinaryTest))
+    elif options.proto == 'multia':
+        suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedBinaryTest))
+    elif options.proto == 'multiac':
+        suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedCompactTest))
+    elif options.proto == 'multic':
+        suite.addTest(loader.loadTestsFromTestCase(MultiplexedCompactTest))
+    elif options.proto == 'multij':
+        suite.addTest(loader.loadTestsFromTestCase(MultiplexedJSONTest))
     else:
         raise AssertionError('Unknown protocol given with --protocol: %s' % options.proto)
     return suite
@@ -325,9 +416,9 @@
                       dest="verbose", const=0,
                       help="minimal output")
     parser.add_option('--protocol', dest="proto", type="string",
-                      help="protocol to use, one of: accel, binary, compact, json")
+                      help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multij")
     parser.add_option('--transport', dest="trans", type="string",
-                      help="transport to use, one of: buffered, framed")
+                      help="transport to use, one of: buffered, framed, http")
     parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary')
     options, args = parser.parse_args()
 
@@ -335,6 +426,10 @@
         sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir))
     sys.path.insert(0, local_libpath())
 
+    if options.http_path:
+        options.trans = 'http'
+
+    from ThriftTest import SecondService
     from ThriftTest import ThriftTest
     from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2
     from thrift.Thrift import TException
@@ -344,6 +439,8 @@
     from thrift.transport import TZlibTransport
     from thrift.protocol import TBinaryProtocol
     from thrift.protocol import TCompactProtocol
+    from thrift.protocol import THeaderProtocol
     from thrift.protocol import TJSONProtocol
+    from thrift.protocol import TMultiplexedProtocol
 
     OwnArgsTestProgram(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=1))
diff --git a/test/py/TestRenderedDoubleConstants.py b/test/py/TestRenderedDoubleConstants.py
new file mode 100644
index 0000000..20903d8
--- /dev/null
+++ b/test/py/TestRenderedDoubleConstants.py
@@ -0,0 +1,177 @@
+#
+# 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 unittest
+
+from DoubleConstantsTest import constants
+
+#
+# In order to run the test under Windows. We need to create symbolic link
+# name 'thrift' to '../src' folder by using:
+#
+# mklink /D thrift ..\src
+#
+
+
+class TestRenderedDoubleConstants(unittest.TestCase):
+    ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST = \
+        "failed to verify a double constant generated by Thrift (expected = %f, got = %f)"
+    ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =\
+        "failed to verify a list item by Thrift (expected = %f, got = %f)"
+    ASSERTION_MESSAGE_FOR_TYPE_CHECKS = "the rendered variable with name %s is not of double type"
+
+    # to make sure the variables inside Thrift files are generated correctly
+    def test_rendered_double_constants(self):
+        EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0
+        EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0
+        EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359
+        EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308
+        EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43
+        EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308
+        EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+            places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+                constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+            places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+                constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+            places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+                constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST,
+            EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS,
+                constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+            places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST,
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST,
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST))
+        self.assertAlmostEqual(
+            constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST,
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, places=7,
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % (
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE,
+                constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST))
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST")
+        self.assertTrue(
+            isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, float),
+            msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS %
+            "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST")
+
+    # to make sure the variables inside Thrift files are generated correctly
+    def test_rendered_double_list(self):
+        EXPECTED_DOUBLE_LIST = [1.0, -100.0, 100.0, 9223372036854775807.0, -9223372036854775807.0, 3.14159265359,
+                                1000000.1, -1000000.1, 1.7e+308, -1.7e+308, 9223372036854775816.43,
+                                -9223372036854775816.43]
+        self.assertEqual(len(constants.DOUBLE_LIST_TEST), len(EXPECTED_DOUBLE_LIST))
+        for i, expectedValue in enumerate(EXPECTED_DOUBLE_LIST):
+            self.assertAlmostEqual(constants.DOUBLE_LIST_TEST[i], expectedValue, places=7)
+
+
+def suite():
+    suite = unittest.TestSuite()
+    loader = unittest.TestLoader()
+    suite.addTest(loader.loadTestsFromTestCase(TestRenderedDoubleConstants))
+    return suite
+
+
+if __name__ == "__main__":
+    unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2))
diff --git a/test/py/TestServer.py b/test/py/TestServer.py
index 04ad62a..aba0d42 100755
--- a/test/py/TestServer.py
+++ b/test/py/TestServer.py
@@ -21,6 +21,7 @@
 from __future__ import division
 import logging
 import os
+import signal
 import sys
 import time
 from optparse import OptionParser
@@ -180,16 +181,22 @@
 def main(options):
     # set up the protocol factory form the --protocol option
     prot_factories = {
-        'binary': TBinaryProtocol.TBinaryProtocolFactory,
-        'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory,
-        'compact': TCompactProtocol.TCompactProtocolFactory,
-        'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory,
-        'json': TJSONProtocol.TJSONProtocolFactory,
+        'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(),
+        'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory(),
+        'binary': TBinaryProtocol.TBinaryProtocolFactory(),
+        'compact': TCompactProtocol.TCompactProtocolFactory(),
+        'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types=[
+            THeaderTransport.THeaderClientType.HEADERS,
+            THeaderTransport.THeaderClientType.FRAMED_BINARY,
+            THeaderTransport.THeaderClientType.UNFRAMED_BINARY,
+            THeaderTransport.THeaderClientType.FRAMED_COMPACT,
+            THeaderTransport.THeaderClientType.UNFRAMED_COMPACT,
+        ]),
+        'json': TJSONProtocol.TJSONProtocolFactory(),
     }
-    pfactory_cls = prot_factories.get(options.proto, None)
-    if pfactory_cls is None:
+    pfactory = prot_factories.get(options.proto, None)
+    if pfactory is None:
         raise AssertionError('Unknown --protocol option: %s' % options.proto)
-    pfactory = pfactory_cls()
     try:
         pfactory.string_length_limit = options.string_limit
         pfactory.container_length_limit = options.container_limit
@@ -201,14 +208,23 @@
     if len(args) > 1:
         raise AssertionError('Only one server type may be specified, not multiple types.')
     server_type = args[0]
+    if options.trans == 'http':
+        server_type = 'THttpServer'
 
     # Set up the handler and processor objects
     handler = TestHandler()
     processor = ThriftTest.Processor(handler)
 
+    global server
+
     # Handle THttpServer as a special case
     if server_type == 'THttpServer':
-        server = THttpServer.THttpServer(processor, ('', options.port), pfactory)
+        if options.ssl:
+            __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.crt")
+            __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.key")
+            server = THttpServer.THttpServer(processor, ('', options.port), pfactory, cert_file=__certfile, key_file=__keyfile)
+        else:
+            server = THttpServer.THttpServer(processor, ('', options.port), pfactory)
         server.serve()
         sys.exit(0)
 
@@ -268,7 +284,15 @@
     server.serve()
 
 
+def exit_gracefully(signum, frame):
+    print("SIGINT received\n")
+    server.shutdown()   # doesn't work properly, yet
+    sys.exit(0)
+
+
 if __name__ == '__main__':
+    signal.signal(signal.SIGINT, exit_gracefully)
+
     parser = OptionParser()
     parser.add_option('--libpydir', type='string', dest='libpydir',
                       help='include this directory to sys.path for locating library code')
@@ -288,12 +312,12 @@
                       dest="verbose", const=0,
                       help="minimal output")
     parser.add_option('--protocol', dest="proto", type="string",
-                      help="protocol to use, one of: accel, binary, compact, json")
+                      help="protocol to use, one of: accel, accelc, binary, compact, json")
     parser.add_option('--transport', dest="trans", type="string",
-                      help="transport to use, one of: buffered, framed")
+                      help="transport to use, one of: buffered, framed, http")
     parser.add_option('--container-limit', dest='container_limit', type='int', default=None)
     parser.add_option('--string-limit', dest='string_limit', type='int', default=None)
-    parser.set_defaults(port=9090, verbose=1, proto='binary')
+    parser.set_defaults(port=9090, verbose=1, proto='binary', transport='buffered')
     options, args = parser.parse_args()
 
     # Print TServer log to stdout so that the test-runner can redirect it to log files
@@ -305,11 +329,13 @@
     from ThriftTest import ThriftTest
     from ThriftTest.ttypes import Xtruct, Xception, Xception2, Insanity
     from thrift.Thrift import TException
+    from thrift.transport import THeaderTransport
     from thrift.transport import TTransport
     from thrift.transport import TSocket
     from thrift.transport import TZlibTransport
     from thrift.protocol import TBinaryProtocol
     from thrift.protocol import TCompactProtocol
+    from thrift.protocol import THeaderProtocol
     from thrift.protocol import TJSONProtocol
     from thrift.server import TServer, TNonblockingServer, THttpServer
 
diff --git a/test/py/generate.cmake b/test/py/generate.cmake
index 46263c8..4ed14cc 100644
--- a/test/py/generate.cmake
+++ b/test/py/generate.cmake
@@ -21,6 +21,13 @@
 generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic gen-py-dynamic)
 generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic,slots gen-py-dynamicslots)
 
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py gen-py-default)
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:slots gen-py-slots)
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:old_style gen-py-oldstyle)
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:no_utf8strings gen-py-no_utf8strings)
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic gen-py-dynamic)
+generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic,slots gen-py-dynamicslots)
+
 generate(${MY_PROJECT_DIR}/test/Recursive.thrift py gen-py-default)
 generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:slots gen-py-slots)
 generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:old_style gen-py-oldstyle)
diff --git a/test/rb/Gemfile b/test/rb/Gemfile
index 58c04aa..4ff0539 100644
--- a/test/rb/Gemfile
+++ b/test/rb/Gemfile
@@ -2,6 +2,6 @@
 
 require "rubygems"
 
-gem "rack", "~> 1.5.2"
-gem "thin", "~> 1.5.0"
-gem "test-unit"
+gem 'rack', '~> 2.0', '>= 2.0.4'
+gem 'thin', '~> 1.7', '>= 1.7.2'
+gem 'test-unit', '~> 3.2', '>= 3.2.7'
diff --git a/test/rb/Makefile.am b/test/rb/Makefile.am
index 4bd4704..cfdc149 100644
--- a/test/rb/Makefile.am
+++ b/test/rb/Makefile.am
@@ -20,6 +20,7 @@
 stubs: $(THRIFT) ../ThriftTest.thrift ../SmallTest.thrift
 	$(THRIFT) --gen rb ../ThriftTest.thrift
 	$(THRIFT) --gen rb ../SmallTest.thrift
+	$(THRIFT) --gen rb ../Recursive.thrift
 
 precross: stubs
 
diff --git a/test/rb/generation/test_recursive.rb b/test/rb/generation/test_recursive.rb
new file mode 100644
index 0000000..e912f72
--- /dev/null
+++ b/test/rb/generation/test_recursive.rb
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+
+require File.join(File.dirname(__FILE__), '../test_helper')
+require 'recursive_types'
+
+class TestRecursiveGeneration < Test::Unit::TestCase
+  CHILD_ITEM = "child item"
+  PARENT_ITEM = "parent item"
+
+  def test_can_create_recursive_tree
+
+    child_tree = RecTree.new
+    child_tree.item = CHILD_ITEM
+
+    parent_tree = RecTree.new
+    parent_tree.item = PARENT_ITEM
+    parent_tree.children = [child_tree]
+
+    assert_equal(PARENT_ITEM, parent_tree.item)
+    assert_equal(1, parent_tree.children.length)
+    assert_equal(CHILD_ITEM, parent_tree.children.first.item)
+    assert_nil(parent_tree.children.first.children)
+  end
+end
diff --git a/test/rb/integration/TestClient.rb b/test/rb/integration/TestClient.rb
index beebe44..639aca9 100755
--- a/test/rb/integration/TestClient.rb
+++ b/test/rb/integration/TestClient.rb
@@ -26,35 +26,63 @@
 require 'thrift'
 require 'thrift_test'
 
-$protocolType = "binary"
+$domain_socket = nil
 $host = "localhost"
 $port = 9090
+$protocolType = "binary"
+$ssl = false
 $transport = "buffered"
+
 ARGV.each do|a|
   if a == "--help"
     puts "Allowed options:"
     puts "\t -h [ --help ] \t produce help message"
-    puts "\t--host arg (=localhost) \t Host to connect"
-    puts "\t--port arg (=9090) \t Port number to listen"
-    puts "\t--protocol arg (=binary) \t protocol: binary, accel"
+    puts "\t--domain-socket arg (=) \t Unix domain socket path"
+    puts "\t--host arg (=localhost) \t Host to connect \t not valid with domain-socket"
+    puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket"
+    puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json"
+    puts "\t--ssl \t use ssl \t not valid with domain-socket"
     puts "\t--transport arg (=buffered) transport: buffered, framed, http"
     exit
+  elsif a.start_with?("--domain-socket")
+    $domain_socket = a.split("=")[1]
   elsif a.start_with?("--host")
     $host = a.split("=")[1]
   elsif a.start_with?("--protocol")
     $protocolType = a.split("=")[1]
+  elsif a == "--ssl"
+    $ssl = true
   elsif a.start_with?("--transport")
     $transport = a.split("=")[1]
   elsif a.start_with?("--port")
     $port = a.split("=")[1].to_i
   end
 end
-ARGV=[]
 
 class SimpleClientTest < Test::Unit::TestCase
   def setup
     unless @socket
-      @socket   = Thrift::Socket.new($host, $port)
+      if $domain_socket.to_s.strip.empty?
+        if $ssl
+          # the working directory for ruby crosstest is test/rb/gen-rb
+          keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys")
+          ctx = OpenSSL::SSL::SSLContext.new
+          ctx.ca_file = File.join(keysDir, "CA.pem")
+          ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "client.crt")))
+          ctx.cert_store = OpenSSL::X509::Store.new
+          ctx.cert_store.add_file(File.join(keysDir, 'server.pem'))
+          ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "client.key")))
+          ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
+          ctx.ssl_version = :SSLv23
+          ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
+          @socket = Thrift::SSLSocket.new($host, $port, nil, ctx)
+        else
+          @socket = Thrift::Socket.new($host, $port)
+        end
+      else
+        @socket = Thrift::UNIXSocket.new($domain_socket)
+      end
+      
       if $transport == "buffered"
         transportFactory = Thrift::BufferedTransport.new(@socket)
       elsif $transport == "framed"
@@ -74,7 +102,7 @@
       else
         raise 'Unknown protocol type'
       end
-      @client   = Thrift::Test::ThriftTest::Client.new(@protocol)
+      @client = Thrift::Test::ThriftTest::Client.new(@protocol)
       @socket.open
     end
   end
diff --git a/test/rb/integration/TestServer.rb b/test/rb/integration/TestServer.rb
index bab723a..7caf6a8 100755
--- a/test/rb/integration/TestServer.rb
+++ b/test/rb/integration/TestServer.rb
@@ -106,21 +106,30 @@
 
 end
 
-protocol = "binary"
+domain_socket = nil
 port = 9090
+protocol = "binary"
+@protocolFactory = nil
+ssl = false
 transport = "buffered"
-@transportFactory = Thrift::BufferedTransportFactory.new
-@protocolFactory = Thrift::BinaryProtocolFactory.new
+@transportFactory = nil
+
 ARGV.each do|a|
   if a == "--help"
     puts "Allowed options:"
     puts "\t -h [ --help ] \t produce help message"
-    puts "\t--port arg (=9090) \t Port number to listen"
-    puts "\t--protocol arg (=binary) \t protocol: binary, accel"
+    puts "\t--domain-socket arg (=) \t Unix domain socket path"
+    puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket"
+    puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json"
+    puts "\t--ssl \t use ssl \t not valid with domain-socket"
     puts "\t--transport arg (=buffered) transport: buffered, framed, http"
     exit
+  elsif a.start_with?("--domain-socket")
+    domain_socket = a.split("=")[1]
   elsif a.start_with?("--protocol")
     protocol = a.split("=")[1]
+  elsif a == "--ssl"
+    ssl = true
   elsif a.start_with?("--transport")
     transport = a.split("=")[1]
   elsif a.start_with?("--port")
@@ -128,9 +137,7 @@
   end
 end
 
-if protocol == "binary"
-  @protocolFactory = Thrift::BinaryProtocolFactory.new
-elsif protocol == ""
+if protocol == "binary" || protocol.to_s.strip.empty?
   @protocolFactory = Thrift::BinaryProtocolFactory.new
 elsif protocol == "compact"
   @protocolFactory = Thrift::CompactProtocolFactory.new
@@ -142,9 +149,7 @@
   raise 'Unknown protocol type'
 end
 
-if transport == "buffered"
-  @transportFactory = Thrift::BufferedTransportFactory.new
-elsif transport == ""
+if transport == "buffered" || transport.to_s.strip.empty?
   @transportFactory = Thrift::BufferedTransportFactory.new
 elsif transport == "framed"
   @transportFactory = Thrift::FramedTransportFactory.new
@@ -152,8 +157,32 @@
   raise 'Unknown transport type'
 end
 
-@handler   = SimpleHandler.new
+@handler = SimpleHandler.new
 @processor = Thrift::Test::ThriftTest::Processor.new(@handler)
-@transport = Thrift::ServerSocket.new(port)
-@server    = Thrift::ThreadedServer.new(@processor, @transport, @transportFactory, @protocolFactory)
+@transport = nil
+if domain_socket.to_s.strip.empty?
+  if ssl
+    # the working directory for ruby crosstest is test/rb/gen-rb
+    keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys")
+    ctx = OpenSSL::SSL::SSLContext.new
+    ctx.ca_file = File.join(keysDir, "CA.pem")
+    ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "server.crt")))
+    ctx.cert_store = OpenSSL::X509::Store.new
+    ctx.cert_store.add_file(File.join(keysDir, 'client.pem'))
+    ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "server.key")))
+    ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
+    ctx.ssl_version = :SSLv23
+    ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
+    @transport = Thrift::SSLServerSocket.new(nil, port, ctx)
+  else
+    @transport = Thrift::ServerSocket.new(port)
+  end
+else
+  @transport = Thrift::UNIXServerSocket.new(domain_socket)
+end
+
+@server = Thrift::ThreadedServer.new(@processor, @transport, @transportFactory, @protocolFactory)
+
+puts "Starting TestServer #{@server.to_s}"
 @server.serve
+puts "done."
diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs
index 297faf9..29b5b88 100644
--- a/test/rs/src/bin/test_client.rs
+++ b/test/rs/src/bin/test_client.rs
@@ -216,7 +216,7 @@
 
     info!("testEnum");
     {
-        verify_expected_result(thrift_test_client.test_enum(Numberz::TWO), Numberz::TWO)?;
+        verify_expected_result(thrift_test_client.test_enum(Numberz::Two), Numberz::Two)?;
     }
 
     info!("testBinary");
@@ -391,7 +391,7 @@
         };
 
         verify_expected_result(
-            thrift_test_client.test_multi(1, -123948, -19234123981, m_snd, Numberz::EIGHT, 81),
+            thrift_test_client.test_multi(1, -123948, -19234123981, m_snd, Numberz::Eight, 81),
             s_cmp,
         )?;
     }
@@ -405,8 +405,8 @@
     // }
     {
         let mut arg_map_usermap: BTreeMap<Numberz, i64> = BTreeMap::new();
-        arg_map_usermap.insert(Numberz::ONE, 4289);
-        arg_map_usermap.insert(Numberz::EIGHT, 19);
+        arg_map_usermap.insert(Numberz::One, 4289);
+        arg_map_usermap.insert(Numberz::Eight, 19);
 
         let mut arg_vec_xtructs: Vec<Xtruct> = Vec::new();
         arg_vec_xtructs.push(
@@ -439,15 +439,15 @@
             user_map: Some(arg_map_usermap),
             xtructs: Some(arg_vec_xtructs),
         };
-        s_cmp_nested_1.insert(Numberz::TWO, insanity.clone());
-        s_cmp_nested_1.insert(Numberz::THREE, insanity.clone());
+        s_cmp_nested_1.insert(Numberz::Two, insanity.clone());
+        s_cmp_nested_1.insert(Numberz::Three, insanity.clone());
 
         let mut s_cmp_nested_2: BTreeMap<Numberz, Insanity> = BTreeMap::new();
         let empty_insanity = Insanity {
             user_map: Some(BTreeMap::new()),
             xtructs: Some(Vec::new()),
         };
-        s_cmp_nested_2.insert(Numberz::SIX, empty_insanity);
+        s_cmp_nested_2.insert(Numberz::Six, empty_insanity);
 
         let mut s_cmp: BTreeMap<UserId, BTreeMap<Numberz, Insanity>> = BTreeMap::new();
         s_cmp.insert(1 as UserId, s_cmp_nested_1);
diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs
index 1976bf4..81c1ec7 100644
--- a/test/rs/src/bin/test_server.rs
+++ b/test/rs/src/bin/test_server.rs
@@ -273,15 +273,15 @@
     ) -> thrift::Result<BTreeMap<UserId, BTreeMap<Numberz, Insanity>>> {
         info!("testInsanity({:?})", argument);
         let mut map_0: BTreeMap<Numberz, Insanity> = BTreeMap::new();
-        map_0.insert(Numberz::TWO, argument.clone());
-        map_0.insert(Numberz::THREE, argument.clone());
+        map_0.insert(Numberz::Two, argument.clone());
+        map_0.insert(Numberz::Three, argument.clone());
 
         let mut map_1: BTreeMap<Numberz, Insanity> = BTreeMap::new();
         let insanity = Insanity {
             user_map: None,
             xtructs: None,
         };
-        map_1.insert(Numberz::SIX, insanity);
+        map_1.insert(Numberz::Six, insanity);
 
         let mut ret: BTreeMap<UserId, BTreeMap<Numberz, Insanity>> = BTreeMap::new();
         ret.insert(1, map_0);
diff --git a/test/test.py b/test/test.py
index 5a015ea..f59256a 100755
--- a/test/test.py
+++ b/test/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements. See the NOTICE file
@@ -18,12 +18,13 @@
 # under the License.
 #
 
-# Apache Thrift - integration test suite
+#
+# Apache Thrift - integration (cross) test suite
 #
 # tests different server-client, protocol and transport combinations
 #
-# This script supports python 2.7 and later.
-# python 3.x is recommended for better stability.
+# This script requires python 3.x due to the improvements in
+# subprocess management that are needed for reliability.
 #
 
 from __future__ import print_function
@@ -38,6 +39,12 @@
 import crossrunner
 from crossrunner.compat import path_join
 
+# 3.3 introduced subprocess timeouts on waiting for child
+req_version = (3, 3)
+cur_version = sys.version_info
+assert (cur_version >= req_version), "Python 3.3 or later is required for proper operation."
+
+
 ROOT_DIR = os.path.dirname(os.path.realpath(os.path.dirname(__file__)))
 TEST_DIR_RELATIVE = 'test'
 TEST_DIR = path_join(ROOT_DIR, TEST_DIR_RELATIVE)
@@ -45,7 +52,7 @@
 CONFIG_FILE = 'tests.json'
 
 
-def run_cross_tests(server_match, client_match, jobs, skip_known_failures, retry_count, regex):
+def run_cross_tests(server_match, client_match, jobs, skip_known_failures, only_known_failures, retry_count, regex):
     logger = multiprocessing.get_logger()
     logger.debug('Collecting tests')
     with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp:
@@ -56,6 +63,10 @@
         print('  servers: %s' % server_match, file=sys.stderr)
         print('  clients: %s' % client_match, file=sys.stderr)
         return False
+    if only_known_failures:
+        logger.debug('Only running known failures')
+        known = crossrunner.load_known_failures(TEST_DIR)
+        tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests))
     if skip_known_failures:
         logger.debug('Skipping known failures')
         known = crossrunner.load_known_failures(TEST_DIR)
@@ -74,7 +85,7 @@
         return False
 
 
-def run_feature_tests(server_match, feature_match, jobs, skip_known_failures, retry_count, regex):
+def run_feature_tests(server_match, feature_match, jobs, skip_known_failures, only_known_failures, retry_count, regex):
     basedir = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE)
     logger = multiprocessing.get_logger()
     logger.debug('Collecting tests')
@@ -88,6 +99,10 @@
         print('  servers: %s' % server_match, file=sys.stderr)
         print('  features: %s' % feature_match, file=sys.stderr)
         return False
+    if only_known_failures:
+        logger.debug('Only running known failures')
+        known = crossrunner.load_known_failures(basedir)
+        tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests))
     if skip_known_failures:
         logger.debug('Skipping known failures')
         known = crossrunner.load_known_failures(basedir)
@@ -123,6 +138,8 @@
     parser.add_argument('-F', '--features', nargs='*', default=None,
                         help='run server feature tests instead of cross language tests')
     parser.add_argument('-R', '--regex', help='test name pattern to run')
+    parser.add_argument('-o', '--only-known_failures', action='store_true', dest='only_known_failures',
+                        help='only execute tests that are known to fail')
     parser.add_argument('-s', '--skip-known-failures', action='store_true', dest='skip_known_failures',
                         help='do not execute tests that are known to fail')
     parser.add_argument('-r', '--retry-count', type=int,
@@ -161,9 +178,13 @@
             options.update_failures, options.print_failures)
     elif options.features is not None:
         features = options.features or ['.*']
-        res = run_feature_tests(server_match, features, options.jobs, options.skip_known_failures, options.retry_count, options.regex)
+        res = run_feature_tests(server_match, features, options.jobs,
+                                options.skip_known_failures, options.only_known_failures,
+                                options.retry_count, options.regex)
     else:
-        res = run_cross_tests(server_match, client_match, options.jobs, options.skip_known_failures, options.retry_count, options.regex)
+        res = run_cross_tests(server_match, client_match, options.jobs,
+                              options.skip_known_failures, options.only_known_failures,
+                              options.retry_count, options.regex)
     return 0 if res else 1
 
 
diff --git a/test/tests.json b/test/tests.json
index c4e07ee..43d6ded 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -43,10 +43,28 @@
     "workdir": "c_glib"
   },
   {
+    "name": "cl",
+    "server": {
+      "command": ["TestServer"],
+      "workdir": "cl",
+      "protocols": ["binary", "multi"],
+      "transports": ["buffered", "framed"],
+      "sockets": ["ip"]
+    },
+    "client": {
+      "command": ["TestClient"],
+      "workdir": "cl",
+      "protocols": ["binary", "multi"],
+      "transports": ["buffered", "framed"],
+      "sockets": ["ip"]
+    }
+  },
+  {
     "name": "d",
     "server": {
       "command": [
-        "thrift_test_server"
+        "thrift_test_server",
+        "--trace"
       ]
     },
     "client": {
@@ -87,7 +105,8 @@
     "transports": [
       "buffered",
       "framed",
-      "http"
+      "http",
+      "zlib"
     ],
     "sockets": [
       "ip",
@@ -102,23 +121,12 @@
   },
   {
     "name": "java",
-    "join_args": true,
-    "command": [
-      "ant",
-      "-f",
-      "build.xml",
-      "-Dno-gen-thrift=\"\"",
-      "-Dtestargs"
-    ],
-    "prepare": [
-      "ant",
-      "-f",
-      "build.xml",
-      "compile-test"
-    ],
+    "join_args": false,
     "server": {
-      "delay": 10,
-      "extra_args": ["run-testserver"],
+      "delay": 15,
+      "command": [
+        "build/runserver"
+      ],
       "protocols": [
         "binary:multi",
         "compact:multic",
@@ -127,7 +135,9 @@
     },
     "client": {
       "timeout": 13,
-      "extra_args": ["run-testclient"],
+      "command": [
+        "build/runclient"
+      ],
       "transports": [
         "http"
       ],
@@ -183,7 +193,8 @@
     ],
     "sockets": [
       "ip",
-      "ip-ssl"
+      "ip-ssl",
+      "domain"
     ],
     "protocols": [
       "compact",
@@ -240,11 +251,20 @@
         "--verbose",
         "--host=localhost",
         "--genpydir=gen-py"
+      ],
+      "protocols": [
+        "multi",
+        "multi:multia",
+        "multic",
+        "multic:multiac",
+        "multij"
       ]
     },
     "transports": [
       "buffered",
-      "framed"
+      "framed",
+      "http",
+      "zlib"
     ],
     "sockets": [
       "ip",
@@ -255,7 +275,8 @@
       "binary",
       "json",
       "binary:accel",
-      "compact:accelc"
+      "compact:accelc",
+      "header"
     ],
     "workdir": "py"
   },
@@ -278,22 +299,32 @@
         "TestClient.py",
         "--host=localhost",
         "--genpydir=gen-py"
+      ],
+      "protocols": [
+        "multi",
+        "multi:multia",
+        "multic",
+        "multic:multiac",
+        "multij"
       ]
     },
     "transports": [
       "buffered",
-      "framed"
+      "framed",
+      "http",
+      "zlib"
     ],
     "sockets": [
-      "ip-ssl",
-      "ip"
+      "ip",
+      "ip-ssl"
     ],
     "protocols": [
       "compact",
       "binary",
       "json",
       "binary:accel",
-      "compact:accelc"
+      "compact:accelc",
+      "header"
     ],
     "workdir": "py"
   },
@@ -325,7 +356,8 @@
     "transports": [
       "buffered",
       "http",
-      "framed"
+      "framed",
+      "zlib"
     ],
     "sockets": [
       "ip",
@@ -356,7 +388,8 @@
       "timeout": 5,
       "command": [
         "ruby",
-        "../integration/TestClient.rb"
+        "../integration/TestClient.rb",
+        "--"
       ]
     },
     "transports": [
@@ -364,13 +397,15 @@
       "framed"
     ],
     "sockets": [
-      "ip"
+      "domain",
+      "ip",
+      "ip-ssl"
     ],
     "protocols": [
-      "compact",
       "binary",
-      "json",
-      "binary:accel"
+      "binary:accel",
+      "compact",
+      "json"
     ],
     "workdir": "rb/gen-rb"
   },
@@ -430,13 +465,12 @@
       "compact",
       "json"
     ],
-    "server-disabled": {
+    "server": {
       "command": [
         "dotnet",
         "run",
-  "--no-build",
-  "--no-restore",
-  "--",
+        "--no-build",
+        "--project=Server/Server.csproj",
         "server"
       ]
     },
@@ -445,13 +479,12 @@
       "command": [
         "dotnet",
         "run",
-  "--no-build",
-  "--no-restore",
-  "--",
+        "--no-build",
+        "--project=Client/Client.csproj",
         "client"
       ]
     },
-    "workdir": "netcore/ThriftTest"
+        "workdir": "netcore"
   },
   {
     "name": "perl",
@@ -685,5 +718,32 @@
       "multic"
     ],
     "workdir": "rs/bin"
+  },
+  {
+    "name": "nodets",
+    "env": {
+      "NODE_PATH": "../lib"
+    },
+    "server": {
+      "command": [
+        "runServer.sh"
+      ]
+    },
+    "client": {
+      "timeout": 6,
+      "command": [
+        "runClient.sh"
+      ]
+    },
+    "protocols": [
+      "binary"
+    ],
+    "sockets": [
+      "ip"
+    ],
+    "transports": [
+      "buffered"
+    ],
+    "workdir": "../lib/nodets/test"
   }
 ]
diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am
index d8ad09c..0499460 100755
--- a/tutorial/Makefile.am
+++ b/tutorial/Makefile.am
@@ -78,6 +78,10 @@
 SUBDIRS += rs
 endif
 
+if WITH_CL
+SUBDIRS += cl
+endif
+
 #
 # generate html for ThriftTest.thrift
 #
diff --git a/tutorial/cl/Makefile.am b/tutorial/cl/Makefile.am
new file mode 100755
index 0000000..2b2013a
--- /dev/null
+++ b/tutorial/cl/Makefile.am
@@ -0,0 +1,65 @@
+#
+# 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.
+
+setup-local-lisp-env: ensure-externals.sh
+	bash ensure-externals.sh
+
+gen-cl: $(top_srcdir)/tutorial/tutorial.thrift
+	$(THRIFT) --gen cl -r $<
+
+ALL_FILE_PREREQS = \
+		   load-locally.lisp \
+		   make-tutorial-server.lisp \
+		   make-tutorial-client.lisp \
+		   shared-implementation.lisp \
+		   thrift-tutorial.asd \
+		   tutorial-implementation.lisp
+
+# NOTE: the server and client cannot be built in parallel
+# because on loading the make-tutorial-* scripts SBCL will
+# attempt to compile their dependencies. Unfortunately,
+# because their dependencies are shared, parallel jobs can
+# end up overwriting or corrupting the compiled files
+all-local: gen-cl setup-local-lisp-env $(ALL_FILE_PREREQS)
+	$(SBCL) --script make-tutorial-server.lisp
+	$(SBCL) --script make-tutorial-client.lisp
+
+tutorialserver: all
+	./TutorialServer
+
+tutorialclient: all
+	./TutorialClient
+
+clean-local:
+	-$(RM) -r gen-*
+	-$(RM) -r externals
+	-$(RM) -r quicklisp
+	-$(RM) -r lib
+	-$(RM) quicklisp.lisp
+	-$(RM) backport-update.zip
+	-$(RM) shared-implementation.fasl
+	-$(RM) tutorial-implementation.fasl
+	-$(RM) TutorialServer
+	-$(RM) TutorialClient
+
+EXTRA_DIST = \
+	tutorial-implementation.lisp \
+	shared-implementation.lisp \
+	thrift-tutorial.asd \
+	make-tutorial-server.lisp \
+	make-tutorial-client.lisp
diff --git a/tutorial/cl/ensure-externals.sh b/tutorial/cl/ensure-externals.sh
new file mode 120000
index 0000000..5ae8c56
--- /dev/null
+++ b/tutorial/cl/ensure-externals.sh
@@ -0,0 +1 @@
+../../lib/cl/ensure-externals.sh
\ No newline at end of file
diff --git a/tutorial/cl/load-locally.lisp b/tutorial/cl/load-locally.lisp
new file mode 100644
index 0000000..b52a0a2
--- /dev/null
+++ b/tutorial/cl/load-locally.lisp
@@ -0,0 +1,22 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+;;;; Just a script for loading the library itself, using bundled dependencies.
+;;;; This is an identical copy of the file in lib/cl.
+
+(require "asdf")
+
+(load (merge-pathnames "externals/bundle.lisp" *load-truename*))
+(asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*))
+(asdf:load-system :thrift)
diff --git a/tutorial/cl/make-tutorial-client.lisp b/tutorial/cl/make-tutorial-client.lisp
new file mode 100644
index 0000000..3a6d861
--- /dev/null
+++ b/tutorial/cl/make-tutorial-client.lisp
@@ -0,0 +1,51 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+(require "asdf")
+(load (merge-pathnames "load-locally.lisp" *load-truename*))
+(asdf:load-system :net.didierverna.clon)
+(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*))
+(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*))
+(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*))
+(asdf:load-system :thrift-tutorial)
+
+(net.didierverna.clon:nickname-package)
+
+(defun main ()
+  "Entry point for the binary."
+  (thrift:with-client (prot #u"thrift://127.0.0.1:9090")
+    (tutorial.calculator:ping prot)
+    (format t "ping()~%")
+    (format t "1 + 1 = ~a~%" (tutorial.calculator:add prot 1 1))
+    (let ((work-instance (tutorial:make-work :num1 5
+                                             :num2 0
+                                             :op tutorial:operation.divide
+                                             :comment "Booya!")))
+      (handler-case (format t
+                            "5 / 0 = ~a - Oh, really? An exception should have been thrown here.~%"
+                            (tutorial.calculator:calculate prot 1 work-instance))
+        (tutorial:invalidoperation (e)
+          (format t "---~%(Expected) Invalid Operation caught: ~%~a~%---~%" e))))
+    (let ((work-instance (tutorial:make-work :num1 15
+                                             :num2 10
+                                             :op tutorial:operation.subtract
+                                             :comment "Playing nice this time.")))
+      (handler-case (format t
+                            "15 - 10 = ~a~%"
+                            (tutorial.calculator:calculate prot 1 work-instance))
+        (tutorial:invalidoperation (e)
+          (format t "---~%(Unexpected) Invalid Operation caught: ~%~a~%---~%" e))))
+    (format t "Check log: ~a~%" (shared.shared-service:get-struct prot 1))))
+
+(clon:dump "TutorialClient" main)
diff --git a/tutorial/cl/make-tutorial-server.lisp b/tutorial/cl/make-tutorial-server.lisp
new file mode 100644
index 0000000..4cf1a90
--- /dev/null
+++ b/tutorial/cl/make-tutorial-server.lisp
@@ -0,0 +1,29 @@
+(in-package #:cl-user)
+
+;;;; Licensed 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.
+
+(require "asdf")
+(load (merge-pathnames "load-locally.lisp" *load-truename*))
+(asdf:load-system :net.didierverna.clon)
+(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*))
+(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*))
+(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*))
+(asdf:load-system :thrift-tutorial)
+
+(net.didierverna.clon:nickname-package)
+
+(defun main ()
+  "Entry point for the binary."
+  (thrift:serve #u"thrift://127.0.0.1:9090" tutorial:calculator))
+
+(clon:dump "TutorialServer" main)
diff --git a/tutorial/cl/shared-implementation.lisp b/tutorial/cl/shared-implementation.lisp
new file mode 100644
index 0000000..c197626
--- /dev/null
+++ b/tutorial/cl/shared-implementation.lisp
@@ -0,0 +1,25 @@
+(in-package #:shared-implementation)
+
+;;;; Licensed 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.
+
+(defvar *structs* (make-hash-table))
+
+(defun shared.shared-service-implementation:get-struct (key)
+  (format t "getStruct(~a)~%" key)
+  (gethash key *structs*))
+
+(defun add-log (key value)
+  (setf (gethash key *structs*)
+        (make-instance 'shared:sharedstruct
+                       :key key
+                       :value (write-to-string value))))
diff --git a/tutorial/cl/thrift-tutorial.asd b/tutorial/cl/thrift-tutorial.asd
new file mode 100644
index 0000000..8a03537
--- /dev/null
+++ b/tutorial/cl/thrift-tutorial.asd
@@ -0,0 +1,17 @@
+;;;; Licensed 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.
+
+(asdf:defsystem #:thrift-tutorial
+  :depends-on (#:thrift-gen-tutorial)
+  :serial t
+  :components ((:file "shared-implementation")
+               (:file "tutorial-implementation")))
diff --git a/tutorial/cl/tutorial-implementation.lisp b/tutorial/cl/tutorial-implementation.lisp
new file mode 100644
index 0000000..5c92fe4
--- /dev/null
+++ b/tutorial/cl/tutorial-implementation.lisp
@@ -0,0 +1,41 @@
+(in-package #:tutorial-implementation)
+
+;;;; Licensed 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.
+
+(defun tutorial.calculator-implementation:ping ()
+  (format t "ping()~%"))
+
+(defun tutorial.calculator-implementation:add (num1 num2)
+  (format t "add(~a, ~a)~%" num1 num2)
+  (+ num1 num2))
+
+(defun tutorial.calculator-implementation:calculate (logid work)
+  (format t "calculate(~a, ~a)~%" logid work)
+  (handler-case
+      (let* ((num1 (tutorial:work-num1 work))
+             (num2 (tutorial:work-num2 work))
+             (op (tutorial:work-op work))
+             (result
+              (cond
+                ((= op tutorial:operation.add) (+ num1 num2))
+                ((= op tutorial:operation.subtract) (- num1 num2))
+                ((= op tutorial:operation.multiply) (* num1 num2))
+                ((= op tutorial:operation.divide) (/ num1 num2)))))
+        (shared-implementation::add-log logid result)
+        result)
+    (division-by-zero () (error 'tutorial:invalidoperation
+                                :why "Division by zero."
+                                :what-op (tutorial:work-op work)))))
+
+(defun tutorial.calculator-implementation:zip ()
+  (format t "zip()~%"))
diff --git a/tutorial/cpp/CppClient.cpp b/tutorial/cpp/CppClient.cpp
index f10c725..5208411 100644
--- a/tutorial/cpp/CppClient.cpp
+++ b/tutorial/cpp/CppClient.cpp
@@ -22,7 +22,6 @@
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TTransportUtils.h>
-#include <thrift/stdcxx.h>
 
 #include "../gen-cpp/Calculator.h"
 
@@ -35,9 +34,9 @@
 using namespace shared;
 
 int main() {
-  stdcxx::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
-  stdcxx::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
-  stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
+  std::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
+  std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
+  std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
   CalculatorClient client(protocol);
 
   try {
diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp
index 80b100e..f7379d5 100644
--- a/tutorial/cpp/CppServer.cpp
+++ b/tutorial/cpp/CppServer.cpp
@@ -27,7 +27,6 @@
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/TToString.h>
-#include <thrift/stdcxx.h>
 
 #include <iostream>
 #include <stdexcept>
@@ -117,7 +116,7 @@
   virtual ~CalculatorCloneFactory() {}
   virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo)
   {
-    stdcxx::shared_ptr<TSocket> sock = stdcxx::dynamic_pointer_cast<TSocket>(connInfo.transport);
+    std::shared_ptr<TSocket> sock = std::dynamic_pointer_cast<TSocket>(connInfo.transport);
     cout << "Incoming connection\n";
     cout << "\tSocketInfo: "  << sock->getSocketInfo() << "\n";
     cout << "\tPeerHost: "    << sock->getPeerHost() << "\n";
@@ -132,18 +131,18 @@
 
 int main() {
   TThreadedServer server(
-    stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()),
-    stdcxx::make_shared<TServerSocket>(9090), //port
-    stdcxx::make_shared<TBufferedTransportFactory>(),
-    stdcxx::make_shared<TBinaryProtocolFactory>());
+    std::make_shared<CalculatorProcessorFactory>(std::make_shared<CalculatorCloneFactory>()),
+    std::make_shared<TServerSocket>(9090), //port
+    std::make_shared<TBufferedTransportFactory>(),
+    std::make_shared<TBinaryProtocolFactory>());
 
   /*
   // if you don't need per-connection state, do the following instead
   TThreadedServer server(
-    stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),
-    stdcxx::make_shared<TServerSocket>(9090), //port
-    stdcxx::make_shared<TBufferedTransportFactory>(),
-    stdcxx::make_shared<TBinaryProtocolFactory>());
+    std::make_shared<CalculatorProcessor>(std::make_shared<CalculatorHandler>()),
+    std::make_shared<TServerSocket>(9090), //port
+    std::make_shared<TBufferedTransportFactory>(),
+    std::make_shared<TBinaryProtocolFactory>());
   */
 
   /**
@@ -151,25 +150,25 @@
 
   // This server only allows one connection at a time, but spawns no threads
   TSimpleServer server(
-    stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),
-    stdcxx::make_shared<TServerSocket>(9090),
-    stdcxx::make_shared<TBufferedTransportFactory>(),
-    stdcxx::make_shared<TBinaryProtocolFactory>());
+    std::make_shared<CalculatorProcessor>(std::make_shared<CalculatorHandler>()),
+    std::make_shared<TServerSocket>(9090),
+    std::make_shared<TBufferedTransportFactory>(),
+    std::make_shared<TBinaryProtocolFactory>());
 
   const int workerCount = 4;
 
-  stdcxx::shared_ptr<ThreadManager> threadManager =
+  std::shared_ptr<ThreadManager> threadManager =
     ThreadManager::newSimpleThreadManager(workerCount);
   threadManager->threadFactory(
-    stdcxx::make_shared<PlatformThreadFactory>());
+    std::make_shared<PlatformThreadFactory>());
   threadManager->start();
 
   // This server allows "workerCount" connection at a time, and reuses threads
   TThreadPoolServer server(
-    stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()),
-    stdcxx::make_shared<TServerSocket>(9090),
-    stdcxx::make_shared<TBufferedTransportFactory>(),
-    stdcxx::make_shared<TBinaryProtocolFactory>(),
+    std::make_shared<CalculatorProcessorFactory>(std::make_shared<CalculatorCloneFactory>()),
+    std::make_shared<TServerSocket>(9090),
+    std::make_shared<TBufferedTransportFactory>(),
+    std::make_shared<TBinaryProtocolFactory>(),
     threadManager);
   */
 
diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs
index 2b801c2..1ff658c 100644
--- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs
+++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs
index b11cbdf..74fa476 100644
--- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs
+++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.0.0")]
-[assembly: AssemblyFileVersion("0.11.0.0")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml
index 51b7ad2..d8ede14 100644
--- a/tutorial/dart/client/pubspec.yaml
+++ b/tutorial/dart/client/pubspec.yaml
@@ -16,7 +16,7 @@
 # under the License.
 
 name: tutorial_client
-version: 0.11.0
+version: 1.0.0
 description: A Dart client implementation of the Apache Thrift tutorial
 author: Apache Thrift Developers <dev@thrift.apache.org>
 homepage: http://thrift.apache.org
@@ -25,7 +25,7 @@
   sdk: ">=1.13.0 <2.0.0"
 
 dependencies:
-  browser: ^0.11.0
+  browser: ^0.10.0
   shared:
     path: ../gen-dart/shared
   thrift:
diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml
index dea5449..a34e26f 100644
--- a/tutorial/dart/console_client/pubspec.yaml
+++ b/tutorial/dart/console_client/pubspec.yaml
@@ -16,7 +16,7 @@
 # under the License.
 
 name: tutorial_console_client
-version: 0.11.0
+version: 1.0.0
 description: >
   A Dart console client to implementation of the Apache Thrift tutorial
 author: Apache Thrift Developers <dev@thrift.apache.org>
diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml
index b925d2f..18d0737 100644
--- a/tutorial/dart/server/pubspec.yaml
+++ b/tutorial/dart/server/pubspec.yaml
@@ -16,7 +16,7 @@
 # under the License.
 
 name: tutorial_server
-version: 0.11.0
+version: 1.0.0
 description: A Dart server to support the Apache Thrift tutorial
 author: Apache Thrift Developers <dev@thrift.apache.org>
 homepage: http://thrift.apache.org
diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dpr b/tutorial/delphi/DelphiClient/DelphiClient.dpr
index 0f380b0..74d0d45 100644
--- a/tutorial/delphi/DelphiClient/DelphiClient.dpr
+++ b/tutorial/delphi/DelphiClient/DelphiClient.dpr
@@ -26,7 +26,7 @@
   Generics.Collections,
   Thrift in '..\..\..\lib\delphi\src\Thrift.pas',
   Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas',
-  Thrift.Console in '..\..\..\lib\delphi\src\Thrift.Console.pas',
+  Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas',
   Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas',
   Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas',
   Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas',
@@ -62,10 +62,10 @@
     transport.Open;
 
     client.ping;
-    Console.WriteLine('ping()');
+    WriteLn('ping()');
 
     sum := client.add( 1, 1);
-    Console.WriteLine( Format( '1+1=%d', [sum]));
+    WriteLn( Format( '1+1=%d', [sum]));
 
     work := TWorkImpl.Create;
 
@@ -74,11 +74,11 @@
     work.Num2 := 0;
     try
       quotient := client.calculate(1, work);
-      Console.WriteLine( 'Whoa we can divide by 0');
-      Console.WriteLine( Format('1/0=%d',[quotient]));
+      WriteLn( 'Whoa we can divide by 0');
+      WriteLn( Format('1/0=%d',[quotient]));
     except
       on io: TInvalidOperation
-      do Console.WriteLine( 'Invalid operation: ' + io.Why);
+      do WriteLn( 'Invalid operation: ' + io.Why);
     end;
 
     work.Op   := TOperation.SUBTRACT;
@@ -86,20 +86,20 @@
     work.Num2 := 10;
     try
       diff := client.calculate( 1, work);
-      Console.WriteLine( Format('15-10=%d', [diff]));
+      WriteLn( Format('15-10=%d', [diff]));
     except
       on io: TInvalidOperation
-      do Console.WriteLine( 'Invalid operation: ' + io.Why);
+      do WriteLn( 'Invalid operation: ' + io.Why);
     end;
 
     log := client.getStruct(1);
-    Console.WriteLine( Format( 'Check log: %s', [log.Value]));
+    WriteLn( Format( 'Check log: %s', [log.Value]));
 
     transport.Close();
 
   except
     on e : Exception
-    do Console.WriteLine( e.ClassName+': '+e.Message);
+    do WriteLn( e.ClassName+': '+e.Message);
   end;
 end;
 
diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj
index 38226b3..d067992 100644
--- a/tutorial/delphi/DelphiClient/DelphiClient.dproj
+++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj
@@ -1,119 +1,119 @@
-    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-        <PropertyGroup>
-            <ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid>
-            <MainSource>DelphiClient.dpr</MainSource>
-            <ProjectVersion>12.3</ProjectVersion>
-            <Basis>True</Basis>
-            <Config Condition="'$(Config)'==''">Debug</Config>
-            <Platform>Win32</Platform>
-            <AppType>Console</AppType>
-            <FrameworkType>None</FrameworkType>
-            <DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''">
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
-            <Cfg_1>true</Cfg_1>
-            <CfgParent>Base</CfgParent>
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
-            <Cfg_2>true</Cfg_2>
-            <CfgParent>Base</CfgParent>
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Base)'!=''">
-            <DCC_UnitSearchPath>..\..\..\lib\delphi\src;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
-            <DCC_ImageBase>00400000</DCC_ImageBase>
-            <DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput>
-            <DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
-            <DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput>
-            <DCC_E>false</DCC_E>
-            <DCC_N>false</DCC_N>
-            <DCC_S>false</DCC_S>
-            <DCC_F>false</DCC_F>
-            <DCC_K>false</DCC_K>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Cfg_1)'!=''">
-            <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
-            <DCC_Optimize>false</DCC_Optimize>
-            <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Cfg_2)'!=''">
-            <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
-            <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
-            <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
-            <DCC_DebugInformation>false</DCC_DebugInformation>
-        </PropertyGroup>
-        <ItemGroup>
-            <DelphiCompile Include="DelphiClient.dpr">
-                <MainSource>MainSource</MainSource>
-            </DelphiCompile>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Console.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/>
-            <DCCReference Include="..\..\gen-delphi\Shared.pas"/>
-            <DCCReference Include="..\..\gen-delphi\Tutorial.pas"/>
-            <BuildConfiguration Include="Release">
-                <Key>Cfg_2</Key>
-                <CfgParent>Base</CfgParent>
-            </BuildConfiguration>
-            <BuildConfiguration Include="Basis">
-                <Key>Base</Key>
-            </BuildConfiguration>
-            <BuildConfiguration Include="Debug">
-                <Key>Cfg_1</Key>
-                <CfgParent>Base</CfgParent>
-            </BuildConfiguration>
-        </ItemGroup>
-        <Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
-        <Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
-        <ProjectExtensions>
-            <Borland.Personality>Delphi.Personality.12</Borland.Personality>
-            <Borland.ProjectType/>
-            <BorlandProject>
-                <Delphi.Personality>
-                    <VersionInfo>
-                        <VersionInfo Name="IncludeVerInfo">True</VersionInfo>
-                        <VersionInfo Name="AutoIncBuild">False</VersionInfo>
-                        <VersionInfo Name="MajorVer">1</VersionInfo>
-                        <VersionInfo Name="MinorVer">0</VersionInfo>
-                        <VersionInfo Name="Release">0</VersionInfo>
-                        <VersionInfo Name="Build">0</VersionInfo>
-                        <VersionInfo Name="Debug">False</VersionInfo>
-                        <VersionInfo Name="PreRelease">False</VersionInfo>
-                        <VersionInfo Name="Special">False</VersionInfo>
-                        <VersionInfo Name="Private">False</VersionInfo>
-                        <VersionInfo Name="DLL">False</VersionInfo>
-                        <VersionInfo Name="Locale">1033</VersionInfo>
-                        <VersionInfo Name="CodePage">1252</VersionInfo>
-                    </VersionInfo>
-                    <VersionInfoKeys>
-                        <VersionInfoKeys Name="CompanyName"/>
-                        <VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys>
-                        <VersionInfoKeys Name="FileVersion">0.11.0.0</VersionInfoKeys>
-                        <VersionInfoKeys Name="InternalName">DelphiClient</VersionInfoKeys>
-                        <VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys>
-                        <VersionInfoKeys Name="LegalTrademarks"/>
-                        <VersionInfoKeys Name="OriginalFilename">DelphiClient.exe</VersionInfoKeys>
-                        <VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys>
-                        <VersionInfoKeys Name="ProductVersion">0.11.0.0</VersionInfoKeys>
-                        <VersionInfoKeys Name="Comments"/>
-                    </VersionInfoKeys>
-                    <Source>
-                        <Source Name="MainSource">DelphiClient.dpr</Source>
-                    </Source>
-                </Delphi.Personality>
-                <Platforms>
-                    <Platform value="Win32">True</Platform>
-                </Platforms>
-            </BorlandProject>
-            <ProjectFileVersion>12</ProjectFileVersion>
-        </ProjectExtensions>
-    </Project>
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+		<PropertyGroup>
+			<ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid>
+			<MainSource>DelphiClient.dpr</MainSource>
+			<ProjectVersion>12.3</ProjectVersion>
+			<Basis>True</Basis>
+			<Config Condition="'$(Config)'==''">Debug</Config>
+			<Platform>Win32</Platform>
+			<AppType>Console</AppType>
+			<FrameworkType>None</FrameworkType>
+			<DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''">
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+			<Cfg_1>true</Cfg_1>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+			<Cfg_2>true</Cfg_2>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Base)'!=''">
+			<DCC_UnitSearchPath>..\..\..\lib\delphi\src;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
+			<DCC_ImageBase>00400000</DCC_ImageBase>
+			<DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput>
+			<DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
+			<DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput>
+			<DCC_E>false</DCC_E>
+			<DCC_N>false</DCC_N>
+			<DCC_S>false</DCC_S>
+			<DCC_F>false</DCC_F>
+			<DCC_K>false</DCC_K>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_1)'!=''">
+			<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+			<DCC_Optimize>false</DCC_Optimize>
+			<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_2)'!=''">
+			<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+			<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+			<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+			<DCC_DebugInformation>false</DCC_DebugInformation>
+		</PropertyGroup>
+		<ItemGroup>
+			<DelphiCompile Include="DelphiClient.dpr">
+				<MainSource>MainSource</MainSource>
+			</DelphiCompile>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Exception.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/>
+			<DCCReference Include="..\..\gen-delphi\Shared.pas"/>
+			<DCCReference Include="..\..\gen-delphi\Tutorial.pas"/>
+			<BuildConfiguration Include="Release">
+				<Key>Cfg_2</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Basis">
+				<Key>Base</Key>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Debug">
+				<Key>Cfg_1</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+		</ItemGroup>
+		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
+		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
+		<ProjectExtensions>
+			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
+			<Borland.ProjectType/>
+			<BorlandProject>
+				<Delphi.Personality>
+					<VersionInfo>
+						<VersionInfo Name="IncludeVerInfo">True</VersionInfo>
+						<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+						<VersionInfo Name="MajorVer">0</VersionInfo>
+						<VersionInfo Name="MinorVer">12</VersionInfo>
+						<VersionInfo Name="Release">0</VersionInfo>
+						<VersionInfo Name="Build">0</VersionInfo>
+						<VersionInfo Name="Debug">False</VersionInfo>
+						<VersionInfo Name="PreRelease">False</VersionInfo>
+						<VersionInfo Name="Special">False</VersionInfo>
+						<VersionInfo Name="Private">False</VersionInfo>
+						<VersionInfo Name="DLL">False</VersionInfo>
+						<VersionInfo Name="Locale">1033</VersionInfo>
+						<VersionInfo Name="CodePage">1252</VersionInfo>
+					</VersionInfo>
+					<VersionInfoKeys>
+						<VersionInfoKeys Name="CompanyName"/>
+						<VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys>
+						<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="InternalName">DelphiClient</VersionInfoKeys>
+						<VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys>
+						<VersionInfoKeys Name="LegalTrademarks"/>
+						<VersionInfoKeys Name="OriginalFilename">DelphiClient.exe</VersionInfoKeys>
+						<VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys>
+						<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="Comments"/>
+					</VersionInfoKeys>
+					<Source>
+						<Source Name="MainSource">DelphiClient.dpr</Source>
+					</Source>
+				</Delphi.Personality>
+				<Platforms>
+					<Platform value="Win32">True</Platform>
+				</Platforms>
+			</BorlandProject>
+			<ProjectFileVersion>12</ProjectFileVersion>
+		</ProjectExtensions>
+	</Project>
diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dpr b/tutorial/delphi/DelphiServer/DelphiServer.dpr
index 9d54a2e..5f42e7e 100644
--- a/tutorial/delphi/DelphiServer/DelphiServer.dpr
+++ b/tutorial/delphi/DelphiServer/DelphiServer.dpr
@@ -28,7 +28,7 @@
   Generics.Collections,
   Thrift in '..\..\..\lib\delphi\src\Thrift.pas',
   Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas',
-  Thrift.Console in '..\..\..\lib\delphi\src\Thrift.Console.pas',
+  Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas',
   Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas',
   Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas',
   Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas',
@@ -86,13 +86,13 @@
 
 procedure TCalculatorHandler.ping;
 begin
-  Console.WriteLine( 'ping()');
+  WriteLn( 'ping()');
 end;
 
 
 function TCalculatorHandler.add(num1: Integer; num2: Integer): Integer;
 begin
-  Console.WriteLine( Format( 'add( %d, %d)', [num1, num2]));
+  WriteLn( Format( 'add( %d, %d)', [num1, num2]));
   result := num1 + num2;
 end;
 
@@ -101,7 +101,7 @@
 var entry : ISharedStruct;
 begin
   try
-    Console.WriteLine( Format('calculate( %d, [%d,%d,%d])', [logid, Ord(w.Op), w.Num1, w.Num2]));
+    WriteLn( Format('calculate( %d, [%d,%d,%d])', [logid, Ord(w.Op), w.Num1, w.Num2]));
 
     case w.Op of
       TOperation.ADD      :  result := w.Num1 + w.Num2;
@@ -126,14 +126,14 @@
 
 function TCalculatorHandler.getStruct(key: Integer): ISharedStruct;
 begin
-  Console.WriteLine( Format( 'getStruct(%d)', [key]));
+  WriteLn( Format( 'getStruct(%d)', [key]));
   result := FLog[key];
 end;
 
 
 procedure TCalculatorHandler.zip;
 begin
-  Console.WriteLine( 'zip()');
+  WriteLn( 'zip()');
 end;
 
 
@@ -152,14 +152,14 @@
     transport := TServerSocketImpl.Create( 9090);
     server    := TSimpleServer.Create( processor, transport);
 
-    Console.WriteLine( 'Starting the server...');
+    WriteLn( 'Starting the server...');
     server.Serve();
 
   except
-    on e: Exception do Console.WriteLine( e.Message);
+    on e: Exception do WriteLn( e.Message);
   end;
 
-  Console.WriteLine('done.');
+  WriteLn('done.');
 end;
 
 
diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj
index ad47a53..e34a6a1 100644
--- a/tutorial/delphi/DelphiServer/DelphiServer.dproj
+++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj
@@ -1,118 +1,118 @@
-    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-        <PropertyGroup>
-            <ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid>
-            <MainSource>DelphiServer.dpr</MainSource>
-            <ProjectVersion>12.3</ProjectVersion>
-            <Basis>True</Basis>
-            <Config Condition="'$(Config)'==''">Debug</Config>
-            <Platform>Win32</Platform>
-            <AppType>Console</AppType>
-            <FrameworkType>None</FrameworkType>
-            <DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''">
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
-            <Cfg_1>true</Cfg_1>
-            <CfgParent>Base</CfgParent>
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
-            <Cfg_2>true</Cfg_2>
-            <CfgParent>Base</CfgParent>
-            <Base>true</Base>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Base)'!=''">
-            <DCC_ImageBase>00400000</DCC_ImageBase>
-            <DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput>
-            <DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
-            <DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput>
-            <DCC_E>false</DCC_E>
-            <DCC_N>false</DCC_N>
-            <DCC_S>false</DCC_S>
-            <DCC_F>false</DCC_F>
-            <DCC_K>false</DCC_K>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Cfg_1)'!=''">
-            <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
-            <DCC_Optimize>false</DCC_Optimize>
-            <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
-        </PropertyGroup>
-        <PropertyGroup Condition="'$(Cfg_2)'!=''">
-            <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
-            <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
-            <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
-            <DCC_DebugInformation>false</DCC_DebugInformation>
-        </PropertyGroup>
-        <ItemGroup>
-            <DelphiCompile Include="DelphiServer.dpr">
-                <MainSource>MainSource</MainSource>
-            </DelphiCompile>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Console.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/>
-            <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/>
-            <DCCReference Include="..\..\gen-delphi\Shared.pas"/>
-            <DCCReference Include="..\..\gen-delphi\Tutorial.pas"/>
-            <BuildConfiguration Include="Release">
-                <Key>Cfg_2</Key>
-                <CfgParent>Base</CfgParent>
-            </BuildConfiguration>
-            <BuildConfiguration Include="Basis">
-                <Key>Base</Key>
-            </BuildConfiguration>
-            <BuildConfiguration Include="Debug">
-                <Key>Cfg_1</Key>
-                <CfgParent>Base</CfgParent>
-            </BuildConfiguration>
-        </ItemGroup>
-        <Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
-        <Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
-        <ProjectExtensions>
-            <Borland.Personality>Delphi.Personality.12</Borland.Personality>
-            <Borland.ProjectType/>
-            <BorlandProject>
-                <Delphi.Personality>
-                    <VersionInfo>
-                        <VersionInfo Name="IncludeVerInfo">True</VersionInfo>
-                        <VersionInfo Name="AutoIncBuild">False</VersionInfo>
-                        <VersionInfo Name="MajorVer">1</VersionInfo>
-                        <VersionInfo Name="MinorVer">0</VersionInfo>
-                        <VersionInfo Name="Release">0</VersionInfo>
-                        <VersionInfo Name="Build">0</VersionInfo>
-                        <VersionInfo Name="Debug">False</VersionInfo>
-                        <VersionInfo Name="PreRelease">False</VersionInfo>
-                        <VersionInfo Name="Special">False</VersionInfo>
-                        <VersionInfo Name="Private">False</VersionInfo>
-                        <VersionInfo Name="DLL">False</VersionInfo>
-                        <VersionInfo Name="Locale">1033</VersionInfo>
-                        <VersionInfo Name="CodePage">1252</VersionInfo>
-                    </VersionInfo>
-                    <VersionInfoKeys>
-                        <VersionInfoKeys Name="CompanyName"/>
-                        <VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys>
-                        <VersionInfoKeys Name="FileVersion">0.11.0.0</VersionInfoKeys>
-                        <VersionInfoKeys Name="InternalName">DelphiServer</VersionInfoKeys>
-                        <VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys>
-                        <VersionInfoKeys Name="LegalTrademarks"/>
-                        <VersionInfoKeys Name="OriginalFilename">DelphiServer.exe</VersionInfoKeys>
-                        <VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys>
-                        <VersionInfoKeys Name="ProductVersion">0.11.0.0</VersionInfoKeys>
-                        <VersionInfoKeys Name="Comments"/>
-                    </VersionInfoKeys>
-                    <Source>
-                        <Source Name="MainSource">DelphiServer.dpr</Source>
-                    </Source>
-                </Delphi.Personality>
-                <Platforms>
-                    <Platform value="Win32">True</Platform>
-                </Platforms>
-            </BorlandProject>
-            <ProjectFileVersion>12</ProjectFileVersion>
-        </ProjectExtensions>
-    </Project>
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+		<PropertyGroup>
+			<ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid>
+			<MainSource>DelphiServer.dpr</MainSource>
+			<ProjectVersion>12.3</ProjectVersion>
+			<Basis>True</Basis>
+			<Config Condition="'$(Config)'==''">Debug</Config>
+			<Platform>Win32</Platform>
+			<AppType>Console</AppType>
+			<FrameworkType>None</FrameworkType>
+			<DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''">
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+			<Cfg_1>true</Cfg_1>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+			<Cfg_2>true</Cfg_2>
+			<CfgParent>Base</CfgParent>
+			<Base>true</Base>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Base)'!=''">
+			<DCC_ImageBase>00400000</DCC_ImageBase>
+			<DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput>
+			<DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias>
+			<DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput>
+			<DCC_E>false</DCC_E>
+			<DCC_N>false</DCC_N>
+			<DCC_S>false</DCC_S>
+			<DCC_F>false</DCC_F>
+			<DCC_K>false</DCC_K>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_1)'!=''">
+			<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+			<DCC_Optimize>false</DCC_Optimize>
+			<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+		</PropertyGroup>
+		<PropertyGroup Condition="'$(Cfg_2)'!=''">
+			<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+			<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+			<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+			<DCC_DebugInformation>false</DCC_DebugInformation>
+		</PropertyGroup>
+		<ItemGroup>
+			<DelphiCompile Include="DelphiServer.dpr">
+				<MainSource>MainSource</MainSource>
+			</DelphiCompile>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Exception.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/>
+			<DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/>
+			<DCCReference Include="..\..\gen-delphi\Shared.pas"/>
+			<DCCReference Include="..\..\gen-delphi\Tutorial.pas"/>
+			<BuildConfiguration Include="Release">
+				<Key>Cfg_2</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Basis">
+				<Key>Base</Key>
+			</BuildConfiguration>
+			<BuildConfiguration Include="Debug">
+				<Key>Cfg_1</Key>
+				<CfgParent>Base</CfgParent>
+			</BuildConfiguration>
+		</ItemGroup>
+		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
+		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
+		<ProjectExtensions>
+			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
+			<Borland.ProjectType/>
+			<BorlandProject>
+				<Delphi.Personality>
+					<VersionInfo>
+						<VersionInfo Name="IncludeVerInfo">True</VersionInfo>
+						<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+						<VersionInfo Name="MajorVer">0</VersionInfo>
+						<VersionInfo Name="MinorVer">12</VersionInfo>
+						<VersionInfo Name="Release">0</VersionInfo>
+						<VersionInfo Name="Build">0</VersionInfo>
+						<VersionInfo Name="Debug">False</VersionInfo>
+						<VersionInfo Name="PreRelease">False</VersionInfo>
+						<VersionInfo Name="Special">False</VersionInfo>
+						<VersionInfo Name="Private">False</VersionInfo>
+						<VersionInfo Name="DLL">False</VersionInfo>
+						<VersionInfo Name="Locale">1033</VersionInfo>
+						<VersionInfo Name="CodePage">1252</VersionInfo>
+					</VersionInfo>
+					<VersionInfoKeys>
+						<VersionInfoKeys Name="CompanyName"/>
+						<VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys>
+						<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="InternalName">DelphiServer</VersionInfoKeys>
+						<VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys>
+						<VersionInfoKeys Name="LegalTrademarks"/>
+						<VersionInfoKeys Name="OriginalFilename">DelphiServer.exe</VersionInfoKeys>
+						<VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys>
+						<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+						<VersionInfoKeys Name="Comments"/>
+					</VersionInfoKeys>
+					<Source>
+						<Source Name="MainSource">DelphiServer.dpr</Source>
+					</Source>
+				</Delphi.Personality>
+				<Platforms>
+					<Platform value="Win32">True</Platform>
+				</Platforms>
+			</BorlandProject>
+			<ProjectFileVersion>12</ProjectFileVersion>
+		</ProjectExtensions>
+	</Project>
diff --git a/tutorial/erl/client.sh b/tutorial/erl/client.sh
deleted file mode 120000
index a417e0d..0000000
--- a/tutorial/erl/client.sh
+++ /dev/null
@@ -1 +0,0 @@
-server.sh
\ No newline at end of file
diff --git a/tutorial/erl/client.sh b/tutorial/erl/client.sh
new file mode 100755
index 0000000..775afb6
--- /dev/null
+++ b/tutorial/erl/client.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+ERL_THRIFT=../../lib/erl
+
+if ! [ -d ${ERL_THRIFT}/ebin ]; then
+    echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}"
+    exit 1
+fi
+
+if ! [ -d gen-erl ]; then
+  ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift
+fi
+
+
+erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \
+     -I gen-erl -o gen-erl gen-erl/*.erl &&
+  erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl &&
+  erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl
diff --git a/tutorial/go/Makefile.am b/tutorial/go/Makefile.am
index a146d5c..bd57d65 100644
--- a/tutorial/go/Makefile.am
+++ b/tutorial/go/Makefile.am
@@ -17,29 +17,22 @@
 # under the License.
 #
 
-if GOVERSION_LT_17
-COMPILER_EXTRAFLAG=":legacy_context"
-endif
-
 gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift
 	$(THRIFT) --gen go$(COMPILER_EXTRAFLAG) -r $<
 
 all-local: gen-go/tutorial/calculator.go
 
-check: src/git.apache.org/thrift.git/lib/go/thrift thirdparty-dep
+check: src/github.com/apache/thrift/lib/go/thrift thirdparty-dep
 	$(THRIFT) -r --gen go$(COMPILER_EXTRAFLAG) $(top_srcdir)/tutorial/tutorial.thrift
 	cp -r gen-go/* src/
 	GOPATH=`pwd` $(GO) build -o go-tutorial ./src
 	GOPATH=`pwd` $(GO) build -o calculator-remote src/tutorial/calculator-remote/calculator-remote.go
 
-src/git.apache.org/thrift.git/lib/go/thrift:
-	mkdir -p src/git.apache.org/thrift.git/lib/go
-	ln -sf $(realpath $(top_srcdir)/lib/go/thrift) src/git.apache.org/thrift.git/lib/go/thrift
+src/github.com/apache/thrift/lib/go/thrift:
+	mkdir -p src/github.com/apache/thrift/lib/go
+	ln -sf $(realpath $(top_srcdir)/lib/go/thrift) src/github.com/apache/thrift/lib/go/thrift
 
 thirdparty-dep:
-	mkdir -p src/golang.org/x/net
-	GOPATH=`pwd`/gopath $(GO) get golang.org/x/net/context
-	ln -sf `pwd`/gopath/src/golang.org/x/net/context src/golang.org/x/net/context
 
 tutorialserver: all
 	GOPATH=`pwd` $(GO) run src/*.go -server=true
@@ -61,9 +54,6 @@
 	src/handler.go \
 	src/server.go \
 	src/main.go \
-	src/go17.go \
-	src/handler_go17.go \
-	src/pre_go17.go \
 	server.crt \
 	server.key
 
diff --git a/tutorial/go/src/client.go b/tutorial/go/src/client.go
index 25616bf..e3ebe00 100644
--- a/tutorial/go/src/client.go
+++ b/tutorial/go/src/client.go
@@ -20,13 +20,16 @@
  */
 
 import (
+	"context"
 	"crypto/tls"
 	"fmt"
 	"tutorial"
 
-	"git.apache.org/thrift.git/lib/go/thrift"
+	"github.com/apache/thrift/lib/go/thrift"
 )
 
+var defaultCtx = context.Background()
+
 func handleClient(client *tutorial.CalculatorClient) (err error) {
 	client.Ping(defaultCtx)
 	fmt.Println("ping()")
diff --git a/tutorial/go/src/go17.go b/tutorial/go/src/go17.go
deleted file mode 100644
index a6003a9..0000000
--- a/tutorial/go/src/go17.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build go1.7
-
-/*
- * 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.
- */
-
-package main
-
-import "context"
-
-var defaultCtx = context.Background()
diff --git a/tutorial/go/src/handler.go b/tutorial/go/src/handler.go
index 783b432..5c0eed0 100644
--- a/tutorial/go/src/handler.go
+++ b/tutorial/go/src/handler.go
@@ -1,5 +1,3 @@
-// +build !go1.7
-
 package main
 
 /*
@@ -22,12 +20,11 @@
  */
 
 import (
+	"context"
 	"fmt"
 	"shared"
 	"strconv"
 	"tutorial"
-
-	"golang.org/x/net/context"
 )
 
 type CalculatorHandler struct {
diff --git a/tutorial/go/src/handler_go17.go b/tutorial/go/src/handler_go17.go
deleted file mode 100644
index d6752cc..0000000
--- a/tutorial/go/src/handler_go17.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// +build go1.7
-
-package main
-
-/*
- * 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 (
-	"context"
-	"fmt"
-	"shared"
-	"strconv"
-	"tutorial"
-)
-
-type CalculatorHandler struct {
-	log map[int]*shared.SharedStruct
-}
-
-func NewCalculatorHandler() *CalculatorHandler {
-	return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)}
-}
-
-func (p *CalculatorHandler) Ping(ctx context.Context) (err error) {
-	fmt.Print("ping()\n")
-	return nil
-}
-
-func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) {
-	fmt.Print("add(", num1, ",", num2, ")\n")
-	return num1 + num2, nil
-}
-
-func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) {
-	fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n")
-	switch w.Op {
-	case tutorial.Operation_ADD:
-		val = w.Num1 + w.Num2
-		break
-	case tutorial.Operation_SUBTRACT:
-		val = w.Num1 - w.Num2
-		break
-	case tutorial.Operation_MULTIPLY:
-		val = w.Num1 * w.Num2
-		break
-	case tutorial.Operation_DIVIDE:
-		if w.Num2 == 0 {
-			ouch := tutorial.NewInvalidOperation()
-			ouch.WhatOp = int32(w.Op)
-			ouch.Why = "Cannot divide by 0"
-			err = ouch
-			return
-		}
-		val = w.Num1 / w.Num2
-		break
-	default:
-		ouch := tutorial.NewInvalidOperation()
-		ouch.WhatOp = int32(w.Op)
-		ouch.Why = "Unknown operation"
-		err = ouch
-		return
-	}
-	entry := shared.NewSharedStruct()
-	entry.Key = logid
-	entry.Value = strconv.Itoa(int(val))
-	k := int(logid)
-	/*
-	   oldvalue, exists := p.log[k]
-	   if exists {
-	     fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n")
-	   } else {
-	     fmt.Print("Adding ", entry, " for key ", k, "\n")
-	   }
-	*/
-	p.log[k] = entry
-	return val, err
-}
-
-func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) {
-	fmt.Print("getStruct(", key, ")\n")
-	v, _ := p.log[int(key)]
-	return v, nil
-}
-
-func (p *CalculatorHandler) Zip(ctx context.Context) (err error) {
-	fmt.Print("zip()\n")
-	return nil
-}
diff --git a/tutorial/go/src/main.go b/tutorial/go/src/main.go
index 63154e3..7730d7b 100644
--- a/tutorial/go/src/main.go
+++ b/tutorial/go/src/main.go
@@ -22,7 +22,7 @@
 import (
 	"flag"
 	"fmt"
-	"git.apache.org/thrift.git/lib/go/thrift"
+	"github.com/apache/thrift/lib/go/thrift"
 	"os"
 )
 
diff --git a/tutorial/go/src/pre_go17.go b/tutorial/go/src/pre_go17.go
deleted file mode 100644
index 10a6fb8..0000000
--- a/tutorial/go/src/pre_go17.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build !go1.7
-
-/*
- * 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.
- */
-
-package main
-
-import "golang.org/x/net/context"
-
-var defaultCtx = context.Background()
diff --git a/tutorial/go/src/server.go b/tutorial/go/src/server.go
index e4c4b97..95708eb 100644
--- a/tutorial/go/src/server.go
+++ b/tutorial/go/src/server.go
@@ -22,7 +22,7 @@
 import (
 	"crypto/tls"
 	"fmt"
-	"git.apache.org/thrift.git/lib/go/thrift"
+	"github.com/apache/thrift/lib/go/thrift"
 	"tutorial"
 )
 
diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal
index 98fbd7b..62e682f 100755
--- a/tutorial/hs/ThriftTutorial.cabal
+++ b/tutorial/hs/ThriftTutorial.cabal
@@ -18,7 +18,7 @@
 --
 
 Name:           ThriftTutorial
-Version:        0.11.0
+Version:        1.0.0
 Cabal-Version:  >= 1.4
 License:        OtherLicense
 Category:       Foreign
diff --git a/tutorial/java/build.xml b/tutorial/java/build.xml
index c895ea9..55cdb8f 100644
--- a/tutorial/java/build.xml
+++ b/tutorial/java/build.xml
@@ -25,11 +25,13 @@
   <property name="build" location="build" />
 
   <path id="libs.classpath">
-    <fileset dir="../../lib/java/build">
-      <include name="*.jar" />
-      <exclude name="-test.jar" />
+    <fileset dir="../../lib/java/build/libs">
+      <include name="libthrift*.jar" />
+      <exclude name="libthrift*test.jar" />
+      <exclude name="libthrift*javadoc.jar" />
+      <exclude name="libthrift*sources.jar" />
     </fileset>
-    <fileset dir="../../lib/java/build/lib">
+    <fileset dir="../../lib/java/build/deps">
       <include name="*.jar" />
     </fileset>
   </path>
@@ -42,7 +44,7 @@
     <pathelement path="${build}" />
     <pathelement path="tutorial.jar" />
   </path>
-  
+
   <target name="init">
     <tstamp />
     <mkdir dir="${build}"/>
diff --git a/tutorial/js/build.xml b/tutorial/js/build.xml
index 2df2e71..03a6e7c 100644
--- a/tutorial/js/build.xml
+++ b/tutorial/js/build.xml
@@ -31,11 +31,13 @@
   <property name="thrift.java.dir" location="${thrift.dir}/lib/java" />
 
   <path id="libs.classpath">
-    <fileset dir="../../lib/java/build">
-      <include name="*.jar" />
-      <exclude name="-test.jar" />
+    <fileset dir="${thrift.java.dir}/build/libs">
+      <include name="libthrift*.jar" />
+      <exclude name="libthrift*test.jar" />
+      <exclude name="libthrift*javadoc.jar" />
+      <exclude name="libthrift*sources.jar" />
     </fileset>
-    <fileset dir="../../lib/java/build/lib">
+    <fileset dir="${thrift.java.dir}/build/deps">
       <include name="*.jar" />
     </fileset>
   </path>
@@ -80,7 +82,7 @@
       <arg line="--gen js -r  ../tutorial.thrift"/>
     </exec>
   </target>
-  
+
   <target name="clean">
     <delete dir="${build}" />
     <delete dir="gen-js"/>
diff --git a/tutorial/js/tutorial.html b/tutorial/js/tutorial.html
index d7f3945..d020bed 100755
--- a/tutorial/js/tutorial.html
+++ b/tutorial/js/tutorial.html
@@ -98,7 +98,7 @@
   </table>
   </form>
   
-  <p>This Java Script example uses <a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;hb=HEAD">tutorial.thrift</a> and a Thrift server using JSON protocol and HTTP transport.
+  <p>This Java Script example uses <a href="https://github.com/apache/thrift/blob/master/tutorial/tutorial.thrift">tutorial.thrift</a> and a Thrift server using JSON protocol and HTTP transport.
   </p>
     <p>
         <a href="http://validator.w3.org/check/referer"><img
diff --git a/tutorial/netcore/Client/Program.cs b/tutorial/netcore/Client/Program.cs
index ae1837b..ce5d8c7 100644
--- a/tutorial/netcore/Client/Program.cs
+++ b/tutorial/netcore/Client/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -42,14 +42,14 @@
         {
             Logger.LogInformation(@"
 Usage: 
-    Client.exe -h
+    Client.exe -help
         will diplay help information 
 
-    Client.exe -t:<transport> -p:<protocol> -mc:<numClients>
+    Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients>
         will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client
 
 Options:
-    -t (transport): 
+    -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
         tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
@@ -57,7 +57,7 @@
         tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090)
         framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
 
-    -p (protocol): 
+    -pr (protocol): 
         binary - (default) binary protocol will be used
         compact - compact protocol will be used
         json - json protocol will be used
@@ -67,7 +67,7 @@
         <numClients> - number of multiple clients to connect to server (max 100, default 1)
 
 Sample:
-    Client.exe -t:tcp -p:binary
+    Client.exe -tr:tcp -p:binary
 ");
         }
 
@@ -75,7 +75,7 @@
         {
             args = args ?? new string[0];
 
-            if (args.Any(x => x.StartsWith("-h", StringComparison.OrdinalIgnoreCase)))
+            if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase)))
             {
                 DisplayHelp();
                 return;
@@ -127,7 +127,7 @@
 
         private static TClientTransport GetTransport(string[] args)
         {
-            var transport = args.FirstOrDefault(x => x.StartsWith("-t"))?.Split(':')?[1];
+            var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1];
 
             Transport selectedTransport;
             if (Enum.TryParse(transport, true, out selectedTransport))
@@ -203,7 +203,7 @@
 
         private static Tuple<Protocol, TProtocol> GetProtocol(string[] args, TClientTransport transport)
         {
-            var protocol = args.FirstOrDefault(x => x.StartsWith("-p"))?.Split(':')?[1];
+            var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1];
 
             Protocol selectedProtocol;
             if (Enum.TryParse(protocol, true, out selectedProtocol))
@@ -352,4 +352,4 @@
             Multiplexed
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tutorial/netcore/Interfaces/.gitignore b/tutorial/netcore/Interfaces/.gitignore
new file mode 100644
index 0000000..2e7446e
--- /dev/null
+++ b/tutorial/netcore/Interfaces/.gitignore
@@ -0,0 +1,3 @@
+# ignore for autogenerated files
+/shared
+/tutorial
diff --git a/tutorial/netcore/Interfaces/Interfaces.csproj b/tutorial/netcore/Interfaces/Interfaces.csproj
index 14fad79..4297a06 100644
--- a/tutorial/netcore/Interfaces/Interfaces.csproj
+++ b/tutorial/netcore/Interfaces/Interfaces.csproj
@@ -17,4 +17,14 @@
   <ItemGroup>
     <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
   </ItemGroup>
+
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" />
+    <Exec Condition="Exists('./../../../compiler/cpp/thrift')" Command="./../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" />
+  </Target>
+
 </Project>
diff --git a/tutorial/netcore/Makefile.am b/tutorial/netcore/Makefile.am
index ef3d618..e305556 100644
--- a/tutorial/netcore/Makefile.am
+++ b/tutorial/netcore/Makefile.am
@@ -19,39 +19,11 @@
 
 SUBDIRS = . 
 
-THRIFT = $(top_builddir)/compiler/cpp/thrift
-
-GENDIR = Interfaces/gen-netcore
-
-# Due to a known issue with "dotnet restore" the Thrift.dll dependency cannot be resolved from cmdline.
-# The problem does NOT affect Visual Studio builds, only cmdline. 
-# - For details see https://github.com/dotnet/cli/issues/3199 and related tickets.
-# - Workaround is to temporarily copy the Thrift project into the solution
-COPYCMD = cp  -u -p -r
-	
-
-THRIFTCODE = \
-			Interfaces/Properties/AssemblyInfo.cs \
-			Client/Properties/AssemblyInfo.cs \
-			Client/Program.cs \
-			Server/Properties/AssemblyInfo.cs \
-			Server/Program.cs 
-
-all-local: \
-	Client.exe
-
-Client.exe: $(THRIFTCODE)
-	$(MKDIR_P) $(GENDIR)
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/tutorial/tutorial.thrift
-	$(DOTNETCORE) --info
-	$(DOTNETCORE) restore
+all-local:
 	$(DOTNETCORE) build
 
 clean-local:
-	$(RM) Client.exe
-	$(RM) Server.exe
 	$(RM) Interfaces.dll
-	$(RM) -r $(GENDIR)
 	$(RM) -r Client/bin
 	$(RM) -r Client/obj
 	$(RM) -r Server/bin
@@ -60,16 +32,11 @@
 	$(RM) -r Interfaces/obj
 
 EXTRA_DIST = \
-			 $(THRIFTCODE) \
-			 Tutorial.sln \
-			 Interfaces/Interfaces.csproj \
-			 Client/Client.csproj \
-			 Client/ThriftTest.pfx \
-			 Client/Properties/launchSettings.json \
-			 Server/Server.csproj \
-			 Server/ThriftTest.pfx \
-			 Server/Properties/launchSettings.json \
-			 build.cmd \
-			 build.sh \
-			 README.md
+	Client \
+	Interfaces \
+	README.md \
+	Server \
+	Tutorial.sln \
+	build.cmd \
+	build.sh
 			 
diff --git a/tutorial/netcore/README.md b/tutorial/netcore/README.md
index 6b2f660..626ef92 100644
--- a/tutorial/netcore/README.md
+++ b/tutorial/netcore/README.md
@@ -1,11 +1,11 @@
 # Building of samples for different platforms 
 
 # Reused components 
-- NET Core Standard 1.6 (SDK 1.0.0-preview2-003121)
-- NET Core App 1.1
+- NET Core Standard 2.0
+- NET Core App 2.0
 
 # How to build
-- Download and install .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)
+- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)
 - Ensure that you have thrift.exe which supports netcore lib and it added to PATH 
 - Go to current folder 
 - Run **build.sh** or **build.cmd** from the root of cloned repository
@@ -18,16 +18,13 @@
 
 - build 
 - go to folder (Client/Server) 
-- run with specifying of correct parameters **dotnet run -t:tcp -p:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**)
+- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**)
 
 #Notes
-- Migration to .NET Standard 2.0 planned for later (Q1 2017) according to  https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/
 - Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) 
 
 #Known issues
 - In trace logging mode you can see some not important internal exceptions
-- Ubuntu 16.10 still not supported fully 
-- There is some problems with .NET Core CLI and usage specific -r|--runtime for building and publishing projects with different target frameworks (netstandard1.6 and netcoreapp1.1) 
 
 # Running of samples 
 Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples 
@@ -39,12 +36,12 @@
     Server.exe -h
         will diplay help information 
 
-    Server.exe -t:<transport> -p:<protocol> 
+    Server.exe -tr:<transport> -pr:<protocol> 
         will run server with specified arguments (tcp transport and binary protocol by default)
 
 Options:
 
-    -t (transport): 
+    -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
         tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
@@ -52,14 +49,14 @@
         tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090)
         framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
 
-    -p (protocol): 
+    -pr (protocol): 
         binary - (default) binary protocol will be used
         compact - compact protocol will be used
         json - json protocol will be used
 		
 Sample:
 
-    Server.exe -t:tcp
+    Server.exe -tr:tcp
 
 **Remarks**:
 
@@ -75,12 +72,12 @@
     Client.exe -h
         will diplay help information 
 
-    Client.exe -t:<transport> -p:<protocol> -mc:<numClients>
+    Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients>
         will run client with specified arguments (tcp transport and binary protocol by default)
 
 Options:
 
-    -t (transport): 
+    -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
         tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
@@ -88,7 +85,7 @@
         tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090)
         framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
 
-    -p (protocol): 
+    -pr (protocol): 
         binary - (default) binary protocol will be used
         compact - compact protocol will be used
         json - json protocol will be used
@@ -98,7 +95,7 @@
 
 Sample:
 
-    Client.exe -t:tcp -p:binary -mc:10
+    Client.exe -tr:tcp -pr:binary -mc:10
 
 Remarks:
 
diff --git a/tutorial/netcore/Server/Program.cs b/tutorial/netcore/Server/Program.cs
index b8cc02e..6a181ba 100644
--- a/tutorial/netcore/Server/Program.cs
+++ b/tutorial/netcore/Server/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -46,7 +46,7 @@
         {
             args = args ?? new string[0];
 
-            if (args.Any(x => x.StartsWith("-h", StringComparison.OrdinalIgnoreCase)))
+            if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase)))
             {
                 DisplayHelp();
                 return;
@@ -69,14 +69,14 @@
         {
             Logger.LogInformation(@"
 Usage: 
-    Server.exe -h
+    Server.exe -help
         will diplay help information 
 
-    Server.exe -t:<transport> -p:<protocol>
+    Server.exe -tr:<transport> -pr:<protocol>
         will run server with specified arguments (tcp transport and binary protocol by default)
 
 Options:
-    -t (transport): 
+    -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
         tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
@@ -84,14 +84,14 @@
         tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090)
         framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
 
-    -p (protocol): 
+    -pr (protocol): 
         binary - (default) binary protocol will be used
         compact - compact protocol will be used
         json - json protocol will be used
         multiplexed - multiplexed protocol will be used
 
 Sample:
-    Server.exe -t:tcp 
+    Server.exe -tr:tcp 
 ");
         }
 
@@ -112,20 +112,18 @@
 
         private static Protocol GetProtocol(string[] args)
         {
-            var transport = args.FirstOrDefault(x => x.StartsWith("-p"))?.Split(':')?[1];
-            Protocol selectedProtocol;
+            var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1];
 
-            Enum.TryParse(transport, true, out selectedProtocol);
+            Enum.TryParse(transport, true, out Protocol selectedProtocol);
 
             return selectedProtocol;
         }
 
         private static Transport GetTransport(string[] args)
         {
-            var transport = args.FirstOrDefault(x => x.StartsWith("-t"))?.Split(':')?[1];
-            Transport selectedTransport;
+            var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1];
 
-            Enum.TryParse(transport, true, out selectedTransport);
+            Enum.TryParse(transport, true, out Transport selectedTransport);
 
             return selectedTransport;
         }
@@ -288,11 +286,10 @@
                     .UseKestrel()
                     .UseUrls("http://localhost:9090")
                     .UseContentRoot(Directory.GetCurrentDirectory())
-                    .UseIISIntegration()
                     .UseStartup<Startup>()
                     .Build();
 
-                host.StartAsync(cancellationToken); // was Run() in earlier .NET Core SDKs?
+                host.RunAsync(cancellationToken).GetAwaiter().GetResult();
             }
 
             public class Startup
diff --git a/tutorial/netcore/Tutorial.sln b/tutorial/netcore/Tutorial.sln
index bff110c..2ddcd46 100644
--- a/tutorial/netcore/Tutorial.sln
+++ b/tutorial/netcore/Tutorial.sln
@@ -1,68 +1,78 @@
-
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.26114.2
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
 		Debug|x64 = Debug|x64
 		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
 		Release|x64 = Release|x64
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{6850CF46-5467-4C65-BD78-871581C539FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{6850CF46-5467-4C65-BD78-871581C539FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{6850CF46-5467-4C65-BD78-871581C539FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{6850CF46-5467-4C65-BD78-871581C539FC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU
+		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU
 		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|x64
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|x64
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|x86
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|x86
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU
 		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|x64
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|x64
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|x86
-		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|x86
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU
+		{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU
 		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|x64
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|x64
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|x86
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|x86
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU
 		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|x64
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|x64
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|x86
-		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|x86
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU
+		{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU
 		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|x64
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|x64
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|x86
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|x86
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU
 		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|x64
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|x64
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|x86
-		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|x86
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU
+		{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D}
+	EndGlobalSection
 EndGlobal
diff --git a/tutorial/netcore/build.cmd b/tutorial/netcore/build.cmd
index e971799..9b84ef2 100644
--- a/tutorial/netcore/build.cmd
+++ b/tutorial/netcore/build.cmd
@@ -19,12 +19,7 @@
 rem  */
 setlocal
 
-cd Interfaces
-thrift  -gen netcore:wcf   -r  ..\..\tutorial.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
 
 :eof
diff --git a/tutorial/netcore/build.sh b/tutorial/netcore/build.sh
index d2cb465..c97e310 100755
--- a/tutorial/netcore/build.sh
+++ b/tutorial/netcore/build.sh
@@ -22,10 +22,5 @@
 #exit if any command fails
 set -e
 
-cd Interfaces
-../../../compiler/cpp/thrift  -gen netcore:wcf   -r  ../../tutorial.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis
index 898261d..745c096 100644
--- a/tutorial/ocaml/_oasis
+++ b/tutorial/ocaml/_oasis
@@ -1,5 +1,5 @@
 Name: tutorial
-Version: 0.11.0
+Version: 1.0.0
 OASISFormat: 0.3
 Synopsis: OCaml Tutorial example
 Authors: Apache Thrift Developers <dev@thrift.apache.org>
diff --git a/tutorial/perl/PerlClient.pl b/tutorial/perl/PerlClient.pl
index 1d59656..7c23289 100644
--- a/tutorial/perl/PerlClient.pl
+++ b/tutorial/perl/PerlClient.pl
@@ -37,10 +37,10 @@
 
 use Data::Dumper;
 
-my $socket    = new Thrift::Socket('localhost',9090);
-my $transport = new Thrift::BufferedTransport($socket,1024,1024);
-my $protocol  = new Thrift::BinaryProtocol($transport);
-my $client    = new tutorial::CalculatorClient($protocol);
+my $socket    = Thrift::Socket->new('localhost',9090);
+my $transport = Thrift::BufferedTransport->new($socket,1024,1024);
+my $protocol  = Thrift::BinaryProtocol->new($transport);
+my $client    = tutorial::CalculatorClient->new($protocol);
 
 
 eval{
@@ -53,7 +53,7 @@
     my $sum = $client->add(1,1);
     print "1+1=$sum\n";
 
-    my $work = new tutorial::Work();
+    my $work = tutorial::Work->new();
 
     $work->op(tutorial::Operation::DIVIDE);
     $work->num1(1);
@@ -63,7 +63,7 @@
         $client->calculate(1, $work);
         print "Whoa! We can divide by zero?\n";
     }; if($@) {
-        warn "InvalidOperation: ".Dumper($@);
+        warn 'InvalidOperation: '.Dumper($@);
     }
 
     $work->op(tutorial::Operation::SUBTRACT);
diff --git a/tutorial/perl/PerlServer.pl b/tutorial/perl/PerlServer.pl
index adec978..dfe6b89 100644
--- a/tutorial/perl/PerlServer.pl
+++ b/tutorial/perl/PerlServer.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 #
 # Licensed to the Apache Software Foundation (ASF) under one
@@ -67,20 +67,20 @@
   } elsif ($op == tutorial::Operation::DIVIDE) {
     if ($num2 == 0)
     {
-      my $x = new tutorial::InvalidOperation;
+      my $x = tutorial::InvalidOperation->new();
       $x->whatOp($op);
       $x->why('Cannot divide by 0');
       die $x;
     }
     $val = $num1 / $num2;
   } else {
-    my $x = new tutorial::InvalidOperation;
+    my $x = tutorial::InvalidOperation->new();
     $x->whatOp($op);
     $x->why('Invalid operation');
     die $x;
   }
 
-  my $log = new shared::SharedStruct;
+  my $log = shared::SharedStruct->new();
   $log->key($logid);
   $log->value(int($val));
   $self->{log}->{$logid} = $log;
@@ -104,10 +104,10 @@
 
 
 eval {
-  my $handler       = new CalculatorHandler;
-  my $processor     = new tutorial::CalculatorProcessor($handler);
-  my $serversocket  = new Thrift::ServerSocket(9090);
-  my $forkingserver = new Thrift::ForkingServer($processor, $serversocket);
+  my $handler       = CalculatorHandler->new();
+  my $processor     = tutorial::CalculatorProcessor->new($handler);
+  my $serversocket  = Thrift::ServerSocket->new(9090);
+  my $forkingserver = Thrift::ForkingServer->new($processor, $serversocket);
   print "Starting the server...\n";
   $forkingserver->serve();
   print "done.\n";
diff --git a/tutorial/php/PhpClient.php b/tutorial/php/PhpClient.php
index d262b8f..92dc3cb 100755
--- a/tutorial/php/PhpClient.php
+++ b/tutorial/php/PhpClient.php
@@ -5,7 +5,7 @@
 
 error_reporting(E_ALL);
 
-require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../lib/php/lib/ClassLoader/ThriftClassLoader.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
diff --git a/tutorial/php/PhpServer.php b/tutorial/php/PhpServer.php
index 22ae43e..5a9b49b 100755
--- a/tutorial/php/PhpServer.php
+++ b/tutorial/php/PhpServer.php
@@ -5,7 +5,7 @@
 
 error_reporting(E_ALL);
 
-require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../lib/php/lib/ClassLoader/ThriftClassLoader.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
diff --git a/tutorial/rs/src/bin/tutorial_client.rs b/tutorial/rs/src/bin/tutorial_client.rs
index 24ab4be..c80fafc 100644
--- a/tutorial/rs/src/bin/tutorial_client.rs
+++ b/tutorial/rs/src/bin/tutorial_client.rs
@@ -22,8 +22,9 @@
 extern crate thrift_tutorial;
 
 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
-use thrift::transport::{ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel,
-                        TTcpChannel, WriteHalf};
+use thrift::transport::{
+    ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel, WriteHalf,
+};
 
 use thrift_tutorial::shared::TSharedServiceSyncClient;
 use thrift_tutorial::tutorial::{CalculatorSyncClient, Operation, TCalculatorSyncClient, Work};
@@ -70,8 +71,7 @@
     let logid = 32;
 
     // let's do...a multiply!
-    let res = client
-        .calculate(logid, Work::new(7, 8, Operation::MULTIPLY, None))?;
+    let res = client.calculate(logid, Work::new(7, 8, Operation::Multiply, None))?;
     println!("multiplied 7 and 8 and got {}", res);
 
     // let's get the log for it
@@ -81,7 +81,7 @@
     // ok - let's be bad :(
     // do a divide by 0
     // logid doesn't matter; won't be recorded
-    let res = client.calculate(77, Work::new(2, 0, Operation::DIVIDE, "we bad".to_owned()));
+    let res = client.calculate(77, Work::new(2, 0, Operation::Divide, "we bad".to_owned()));
 
     // we should have gotten an exception back
     match res {
@@ -103,8 +103,7 @@
 type ClientInputProtocol = TCompactInputProtocol<TFramedReadTransport<ReadHalf<TTcpChannel>>>;
 type ClientOutputProtocol = TCompactOutputProtocol<TFramedWriteTransport<WriteHalf<TTcpChannel>>>;
 
-fn new_client
-    (
+fn new_client(
     host: &str,
     port: u16,
 ) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>> {
diff --git a/tutorial/rs/src/bin/tutorial_server.rs b/tutorial/rs/src/bin/tutorial_server.rs
index 8db8eed..95b1a2b 100644
--- a/tutorial/rs/src/bin/tutorial_server.rs
+++ b/tutorial/rs/src/bin/tutorial_server.rs
@@ -65,7 +65,9 @@
     let o_prot_fact = TCompactOutputProtocolFactory::new();
 
     // demux incoming messages
-    let processor = CalculatorSyncProcessor::new(CalculatorServer { ..Default::default() });
+    let processor = CalculatorSyncProcessor::new(CalculatorServer {
+        ..Default::default()
+    });
 
     // create the server and start listening
     let mut server = TServer::new(
@@ -87,7 +89,9 @@
 
 impl Default for CalculatorServer {
     fn default() -> CalculatorServer {
-        CalculatorServer { log: Mutex::new(HashMap::new()) }
+        CalculatorServer {
+            log: Mutex::new(HashMap::new()),
+        }
     }
 }
 
@@ -122,29 +126,25 @@
 
         let res = if let Some(ref op) = w.op {
             if w.num1.is_none() || w.num2.is_none() {
-                Err(
-                    InvalidOperation {
-                        what_op: Some(*op as i32),
-                        why: Some("no operands specified".to_owned()),
-                    },
-                )
+                Err(InvalidOperation {
+                    what_op: Some(*op as i32),
+                    why: Some("no operands specified".to_owned()),
+                })
             } else {
                 // so that I don't have to call unwrap() multiple times below
                 let num1 = w.num1.as_ref().expect("operands checked");
                 let num2 = w.num2.as_ref().expect("operands checked");
 
                 match *op {
-                    Operation::ADD => Ok(num1 + num2),
-                    Operation::SUBTRACT => Ok(num1 - num2),
-                    Operation::MULTIPLY => Ok(num1 * num2),
-                    Operation::DIVIDE => {
+                    Operation::Add => Ok(num1 + num2),
+                    Operation::Subtract => Ok(num1 - num2),
+                    Operation::Multiply => Ok(num1 * num2),
+                    Operation::Divide => {
                         if *num2 == 0 {
-                            Err(
-                                InvalidOperation {
-                                    what_op: Some(*op as i32),
-                                    why: Some("divide by 0".to_owned()),
-                                },
-                            )
+                            Err(InvalidOperation {
+                                what_op: Some(*op as i32),
+                                why: Some("divide by 0".to_owned()),
+                            })
                         } else {
                             Ok(num1 / num2)
                         }
@@ -152,7 +152,10 @@
                 }
             }
         } else {
-            Err(InvalidOperation::new(None, "no operation specified".to_owned()),)
+            Err(InvalidOperation::new(
+                None,
+                "no operation specified".to_owned(),
+            ))
         };
 
         // if the operation was successful log it
diff --git a/tutorial/shared.thrift b/tutorial/shared.thrift
index 3cc1bb3..f1685bd 100644
--- a/tutorial/shared.thrift
+++ b/tutorial/shared.thrift
@@ -22,6 +22,7 @@
  * these definitions.
  */
 
+namespace cl shared
 namespace cpp shared
 namespace d share // "shared" would collide with the eponymous D keyword.
 namespace dart shared
diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift
index f8c5320..e027546 100644
--- a/tutorial/tutorial.thrift
+++ b/tutorial/tutorial.thrift
@@ -62,6 +62,8 @@
  * Thrift files can namespace, package, or prefix their output in various
  * target languages.
  */
+
+namespace cl tutorial
 namespace cpp tutorial
 namespace d tutorial
 namespace dart tutorial