Add support for rapidjson as the JSON library

nlohmann is still the default, but if `CPPDAP_JSON_DIR` points to rapidjson, then this will be used instead

Most of this was upstreamed from:
https://fuchsia-review.googlesource.com/c/third_party/github.com/google/cppdap/+/456566
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a41d6ae..2ec3ac0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,13 +65,33 @@
 endif(CPPDAP_BUILD_TESTS)
 
 ###########################################################
+# JSON library
+###########################################################
+if(NOT DEFINED CPPDAP_JSON_LIBRARY)
+    # Attempt to detect JSON library from CPPDAP_JSON_DIR
+    if(NOT EXISTS "${CPPDAP_JSON_DIR}")
+        message(FATAL_ERROR "CPPDAP_JSON_DIR '${CPPDAP_JSON_DIR}' does not exist")
+    endif()
+
+    if(EXISTS "${CPPDAP_JSON_DIR}/include/nlohmann")
+        set(CPPDAP_JSON_LIBRARY "nlohmann")
+    elseif(EXISTS "${CPPDAP_JSON_DIR}/include/rapidjson")
+        set(CPPDAP_JSON_LIBRARY "rapid")
+    else()
+        message(FATAL_ERROR "Could not determine JSON library from ${CPPDAP_JSON_LIBRARY}")
+    endif()
+endif()
+string(TOUPPER ${CPPDAP_JSON_LIBRARY} CPPDAP_JSON_LIBRARY_UPPER)
+
+###########################################################
 # File lists
 ###########################################################
 set(CPPDAP_LIST
     ${CPPDAP_SRC_DIR}/content_stream.cpp
     ${CPPDAP_SRC_DIR}/io.cpp
-    ${CPPDAP_SRC_DIR}/json_serializer.cpp
+    ${CPPDAP_SRC_DIR}/${CPPDAP_JSON_LIBRARY}_json_serializer.cpp
     ${CPPDAP_SRC_DIR}/network.cpp
+    ${CPPDAP_SRC_DIR}/null_json_serializer.cpp
     ${CPPDAP_SRC_DIR}/protocol_events.cpp
     ${CPPDAP_SRC_DIR}/protocol_requests.cpp
     ${CPPDAP_SRC_DIR}/protocol_response.cpp
@@ -117,6 +137,11 @@
         )
     endif()
 
+    # Add define for JSON library in use
+    set_target_properties(${target} PROPERTIES
+        COMPILE_DEFINITIONS "CPPDAP_JSON_${CPPDAP_JSON_LIBRARY_UPPER}=1"
+    )
+
     # Treat all warnings as errors
     if(CPPDAP_WARNINGS_AS_ERRORS)
         if(MSVC)
@@ -151,9 +176,7 @@
 
 # dap
 add_library(cppdap STATIC ${CPPDAP_LIST})
-set_target_properties(cppdap PROPERTIES
-    POSITION_INDEPENDENT_CODE 1
-)
+set_target_properties(cppdap PROPERTIES POSITION_INDEPENDENT_CODE 1)
 
 target_include_directories(cppdap PRIVATE "${CPPDAP_JSON_DIR}/include/")
 
diff --git a/src/chan.h b/src/chan.h
index c4183c2..f2345e9 100644
--- a/src/chan.h
+++ b/src/chan.h
@@ -87,4 +87,4 @@
 
 }  // namespace dap
 
-#endif  // dap_chan_h
\ No newline at end of file
+#endif  // dap_chan_h
diff --git a/src/io.cpp b/src/io.cpp
index 04db817..3ee972e 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -145,7 +145,7 @@
   const bool closable;
   std::mutex readMutex;
   std::mutex writeMutex;
-  std::atomic<bool> closed = { false };
+  std::atomic<bool> closed = {false};
 };
 
 class ReaderSpy : public dap::Reader {
@@ -254,4 +254,4 @@
   return w->write(buf, strlen(buf));
 }
 
-}  // namespace dap
\ No newline at end of file
+}  // namespace dap
diff --git a/src/json_serializer.h b/src/json_serializer.h
index 4ae4e11..9bc26d5 100644
--- a/src/json_serializer.h
+++ b/src/json_serializer.h
@@ -1,4 +1,4 @@
-// Copyright 2019 Google LLC
+// Copyright 2020 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,119 +15,28 @@
 #ifndef dap_json_serializer_h
 #define dap_json_serializer_h
 
-#include "dap/protocol.h"
-#include "dap/serialization.h"
-#include "dap/types.h"
-
-#include <nlohmann/json_fwd.hpp>
+#if defined(CPPDAP_JSON_NLOHMANN)
+#include "nlohmann_json_serializer.h"
+#elif defined(CPPDAP_JSON_RAPID)
+#include "rapid_json_serializer.h"
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
 
 namespace dap {
 namespace json {
 
-struct Deserializer : public dap::Deserializer {
-  explicit Deserializer(const std::string&);
-  ~Deserializer();
-
-  // dap::Deserializer compliance
-  bool deserialize(boolean* v) const override;
-  bool deserialize(integer* v) const override;
-  bool deserialize(number* v) const override;
-  bool deserialize(string* v) const override;
-  bool deserialize(object* v) const override;
-  bool deserialize(any* v) const override;
-  size_t count() const override;
-  bool array(const std::function<bool(dap::Deserializer*)>&) const override;
-  bool field(const std::string& name,
-             const std::function<bool(dap::Deserializer*)>&) const override;
-
-  // Unhide base overloads
-  template <typename T>
-  inline bool field(const std::string& name, T* v) {
-    return dap::Deserializer::field(name, v);
-  }
-
-  template <typename T,
-            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
-  inline bool deserialize(T* v) const {
-    return dap::Deserializer::deserialize(v);
-  }
-
-  template <typename T>
-  inline bool deserialize(dap::array<T>* v) const {
-    return dap::Deserializer::deserialize(v);
-  }
-
-  template <typename T>
-  inline bool deserialize(dap::optional<T>* v) const {
-    return dap::Deserializer::deserialize(v);
-  }
-
-  template <typename T0, typename... Types>
-  inline bool deserialize(dap::variant<T0, Types...>* v) const {
-    return dap::Deserializer::deserialize(v);
-  }
-
-  template <typename T>
-  inline bool field(const std::string& name, T* v) const {
-    return dap::Deserializer::deserialize(name, v);
-  }
-
- private:
-  Deserializer(const nlohmann::json*);
-  const nlohmann::json* const json;
-  const bool ownsJson;
-};
-
-struct Serializer : public dap::Serializer {
-  Serializer();
-  ~Serializer();
-
-  std::string dump() const;
-
-  // dap::Serializer compliance
-  bool serialize(boolean v) override;
-  bool serialize(integer v) override;
-  bool serialize(number v) override;
-  bool serialize(const string& v) override;
-  bool serialize(const dap::object& v) override;
-  bool serialize(const any& v) override;
-  bool array(size_t count,
-             const std::function<bool(dap::Serializer*)>&) override;
-  bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
-  void remove() override;
-
-  // Unhide base overloads
-  template <typename T,
-            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
-  inline bool serialize(const T& v) {
-    return dap::Serializer::serialize(v);
-  }
-
-  template <typename T>
-  inline bool serialize(const dap::array<T>& v) {
-    return dap::Serializer::serialize(v);
-  }
-
-  template <typename T>
-  inline bool serialize(const dap::optional<T>& v) {
-    return dap::Serializer::serialize(v);
-  }
-
-  template <typename T0, typename... Types>
-  inline bool serialize(const dap::variant<T0, Types...>& v) {
-    return dap::Serializer::serialize(v);
-  }
-
-  inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
-
- private:
-  Serializer(nlohmann::json*);
-  nlohmann::json* const json;
-  const bool ownsJson;
-  bool removed = false;
-};
+#if defined(CPPDAP_JSON_NLOHMANN)
+using Deserializer = NlohmannDeserializer;
+using Serializer = NlohmannSerializer;
+#elif defined(CPPDAP_JSON_RAPID)
+using Deserializer = RapidDeserializer;
+using Serializer = RapidSerializer;
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
 
 }  // namespace json
 }  // namespace dap
 
-#endif  // dap_json_serializer_h
\ No newline at end of file
+#endif  // dap_json_serializer_h
diff --git a/src/json_serializer.cpp b/src/nlohmann_json_serializer.cpp
similarity index 61%
rename from src/json_serializer.cpp
rename to src/nlohmann_json_serializer.cpp
index 9d44dc1..7aa0399 100644
--- a/src/json_serializer.cpp
+++ b/src/nlohmann_json_serializer.cpp
@@ -12,55 +12,32 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "json_serializer.h"
+#include "nlohmann_json_serializer.h"
+
+#include "null_json_serializer.h"
 
 // Disable JSON exceptions. We should be guarding against any exceptions being
 // fired in this file.
 #define JSON_NOEXCEPTION 1
 #include <nlohmann/json.hpp>
 
-namespace {
-
-struct NullDeserializer : public dap::Deserializer {
-  static NullDeserializer instance;
-
-  bool deserialize(dap::boolean*) const override { return false; }
-  bool deserialize(dap::integer*) const override { return false; }
-  bool deserialize(dap::number*) const override { return false; }
-  bool deserialize(dap::string*) const override { return false; }
-  bool deserialize(dap::object*) const override { return false; }
-  bool deserialize(dap::any*) const override { return false; }
-  size_t count() const override { return 0; }
-  bool array(const std::function<bool(dap::Deserializer*)>&) const override {
-    return false;
-  }
-  bool field(const std::string&,
-             const std::function<bool(dap::Deserializer*)>&) const override {
-    return false;
-  }
-};
-
-NullDeserializer NullDeserializer::instance;
-
-}  // anonymous namespace
-
 namespace dap {
 namespace json {
 
-Deserializer::Deserializer(const std::string& str)
+NlohmannDeserializer::NlohmannDeserializer(const std::string& str)
     : json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))),
       ownsJson(true) {}
 
-Deserializer::Deserializer(const nlohmann::json* json)
+NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json)
     : json(json), ownsJson(false) {}
 
-Deserializer::~Deserializer() {
+NlohmannDeserializer::~NlohmannDeserializer() {
   if (ownsJson) {
     delete json;
   }
 }
 
-bool Deserializer::deserialize(dap::boolean* v) const {
+bool NlohmannDeserializer::deserialize(dap::boolean* v) const {
   if (!json->is_boolean()) {
     return false;
   }
@@ -68,7 +45,7 @@
   return true;
 }
 
-bool Deserializer::deserialize(dap::integer* v) const {
+bool NlohmannDeserializer::deserialize(dap::integer* v) const {
   if (!json->is_number_integer()) {
     return false;
   }
@@ -76,7 +53,7 @@
   return true;
 }
 
-bool Deserializer::deserialize(dap::number* v) const {
+bool NlohmannDeserializer::deserialize(dap::number* v) const {
   if (!json->is_number()) {
     return false;
   }
@@ -84,7 +61,7 @@
   return true;
 }
 
-bool Deserializer::deserialize(dap::string* v) const {
+bool NlohmannDeserializer::deserialize(dap::string* v) const {
   if (!json->is_string()) {
     return false;
   }
@@ -92,10 +69,10 @@
   return true;
 }
 
-bool Deserializer::deserialize(dap::object* v) const {
+bool NlohmannDeserializer::deserialize(dap::object* v) const {
   v->reserve(json->size());
   for (auto& el : json->items()) {
-    Deserializer d(&el.value());
+    NlohmannDeserializer d(&el.value());
     dap::any val;
     if (!d.deserialize(&val)) {
       return false;
@@ -105,7 +82,7 @@
   return true;
 }
 
-bool Deserializer::deserialize(dap::any* v) const {
+bool NlohmannDeserializer::deserialize(dap::any* v) const {
   if (json->is_boolean()) {
     *v = dap::boolean(json->get<bool>());
   } else if (json->is_number_float()) {
@@ -122,17 +99,17 @@
   return true;
 }
 
-size_t Deserializer::count() const {
+size_t NlohmannDeserializer::count() const {
   return json->size();
 }
 
-bool Deserializer::array(
+bool NlohmannDeserializer::array(
     const std::function<bool(dap::Deserializer*)>& cb) const {
   if (!json->is_array()) {
     return false;
   }
   for (size_t i = 0; i < json->size(); i++) {
-    Deserializer d(&(*json)[i]);
+    NlohmannDeserializer d(&(*json)[i]);
     if (!cb(&d)) {
       return false;
     }
@@ -140,7 +117,7 @@
   return true;
 }
 
-bool Deserializer::field(
+bool NlohmannDeserializer::field(
     const std::string& name,
     const std::function<bool(dap::Deserializer*)>& cb) const {
   if (!json->is_structured()) {
@@ -151,47 +128,49 @@
     return cb(&NullDeserializer::instance);
   }
   auto obj = *it;
-  Deserializer d(&obj);
+  NlohmannDeserializer d(&obj);
   return cb(&d);
 }
 
-Serializer::Serializer() : json(new nlohmann::json()), ownsJson(true) {}
+NlohmannSerializer::NlohmannSerializer()
+    : json(new nlohmann::json()), ownsJson(true) {}
 
-Serializer::Serializer(nlohmann::json* json) : json(json), ownsJson(false) {}
+NlohmannSerializer::NlohmannSerializer(nlohmann::json* json)
+    : json(json), ownsJson(false) {}
 
-Serializer::~Serializer() {
+NlohmannSerializer::~NlohmannSerializer() {
   if (ownsJson) {
     delete json;
   }
 }
 
-std::string Serializer::dump() const {
+std::string NlohmannSerializer::dump() const {
   return json->dump();
 }
 
-bool Serializer::serialize(dap::boolean v) {
+bool NlohmannSerializer::serialize(dap::boolean v) {
   *json = (bool)v;
   return true;
 }
 
-bool Serializer::serialize(dap::integer v) {
+bool NlohmannSerializer::serialize(dap::integer v) {
   *json = (int)v;
   return true;
 }
 
-bool Serializer::serialize(dap::number v) {
+bool NlohmannSerializer::serialize(dap::number v) {
   *json = (double)v;
   return true;
 }
 
-bool Serializer::serialize(const dap::string& v) {
+bool NlohmannSerializer::serialize(const dap::string& v) {
   *json = v;
   return true;
 }
 
-bool Serializer::serialize(const dap::object& v) {
+bool NlohmannSerializer::serialize(const dap::object& v) {
   for (auto& it : v) {
-    Serializer s(&(*json)[it.first]);
+    NlohmannSerializer s(&(*json)[it.first]);
     if (!s.serialize(it.second)) {
       return false;
     }
@@ -199,7 +178,7 @@
   return true;
 }
 
-bool Serializer::serialize(const dap::any& v) {
+bool NlohmannSerializer::serialize(const dap::any& v) {
   if (v.is<dap::boolean>()) {
     *json = (bool)v.get<dap::boolean>();
   } else if (v.is<dap::integer>()) {
@@ -216,11 +195,12 @@
   return true;
 }
 
-bool Serializer::array(size_t count,
-                       const std::function<bool(dap::Serializer*)>& cb) {
+bool NlohmannSerializer::array(
+    size_t count,
+    const std::function<bool(dap::Serializer*)>& cb) {
   *json = std::vector<int>();
   for (size_t i = 0; i < count; i++) {
-    Serializer s(&(*json)[i]);
+    NlohmannSerializer s(&(*json)[i]);
     if (!cb(&s)) {
       return false;
     }
@@ -228,13 +208,14 @@
   return true;
 }
 
-bool Serializer::object(const std::function<bool(dap::FieldSerializer*)>& cb) {
+bool NlohmannSerializer::object(
+    const std::function<bool(dap::FieldSerializer*)>& cb) {
   struct FS : public FieldSerializer {
     nlohmann::json* const json;
 
     FS(nlohmann::json* json) : json(json) {}
     bool field(const std::string& name, const SerializeFunc& cb) override {
-      Serializer s(&(*json)[name]);
+      NlohmannSerializer s(&(*json)[name]);
       auto res = cb(&s);
       if (s.removed) {
         json->erase(name);
@@ -248,7 +229,7 @@
   return cb(&fs);
 }
 
-void Serializer::remove() {
+void NlohmannSerializer::remove() {
   removed = true;
 }
 
diff --git a/src/nlohmann_json_serializer.h b/src/nlohmann_json_serializer.h
new file mode 100644
index 0000000..f75fe78
--- /dev/null
+++ b/src/nlohmann_json_serializer.h
@@ -0,0 +1,133 @@
+// Copyright 2019 Google LLC
+//
+// 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
+//
+//     https://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 dap_nlohmann_json_serializer_h
+#define dap_nlohmann_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+#include <nlohmann/json_fwd.hpp>
+
+namespace dap {
+namespace json {
+
+struct NlohmannDeserializer : public dap::Deserializer {
+  explicit NlohmannDeserializer(const std::string&);
+  ~NlohmannDeserializer();
+
+  // dap::Deserializer compliance
+  bool deserialize(boolean* v) const override;
+  bool deserialize(integer* v) const override;
+  bool deserialize(number* v) const override;
+  bool deserialize(string* v) const override;
+  bool deserialize(object* v) const override;
+  bool deserialize(any* v) const override;
+  size_t count() const override;
+  bool array(const std::function<bool(dap::Deserializer*)>&) const override;
+  bool field(const std::string& name,
+             const std::function<bool(dap::Deserializer*)>&) const override;
+
+  // Unhide base overloads
+  template <typename T>
+  inline bool field(const std::string& name, T* v) {
+    return dap::Deserializer::field(name, v);
+  }
+
+  template <typename T,
+            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+  inline bool deserialize(T* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool deserialize(dap::array<T>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool deserialize(dap::optional<T>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T0, typename... Types>
+  inline bool deserialize(dap::variant<T0, Types...>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool field(const std::string& name, T* v) const {
+    return dap::Deserializer::deserialize(name, v);
+  }
+
+ private:
+  NlohmannDeserializer(const nlohmann::json*);
+  const nlohmann::json* const json;
+  const bool ownsJson;
+};
+
+struct NlohmannSerializer : public dap::Serializer {
+  NlohmannSerializer();
+  ~NlohmannSerializer();
+
+  std::string dump() const;
+
+  // dap::Serializer compliance
+  bool serialize(boolean v) override;
+  bool serialize(integer v) override;
+  bool serialize(number v) override;
+  bool serialize(const string& v) override;
+  bool serialize(const dap::object& v) override;
+  bool serialize(const any& v) override;
+  bool array(size_t count,
+             const std::function<bool(dap::Serializer*)>&) override;
+  bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
+  void remove() override;
+
+  // Unhide base overloads
+  template <typename T,
+            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+  inline bool serialize(const T& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T>
+  inline bool serialize(const dap::array<T>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T>
+  inline bool serialize(const dap::optional<T>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T0, typename... Types>
+  inline bool serialize(const dap::variant<T0, Types...>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
+
+ private:
+  NlohmannSerializer(nlohmann::json*);
+  nlohmann::json* const json;
+  const bool ownsJson;
+  bool removed = false;
+};
+
+}  // namespace json
+}  // namespace dap
+
+#endif  // dap_nlohmann_json_serializer_h
\ No newline at end of file
diff --git a/src/null_json_serializer.cpp b/src/null_json_serializer.cpp
new file mode 100644
index 0000000..5aa5a03
--- /dev/null
+++ b/src/null_json_serializer.cpp
@@ -0,0 +1,23 @@
+// Copyright 2020 Google LLC
+//
+// 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
+//
+//     https://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 "null_json_serializer.h"
+
+namespace dap {
+namespace json {
+
+NullDeserializer NullDeserializer::instance;
+
+}  // namespace json
+}  // namespace dap
diff --git a/src/null_json_serializer.h b/src/null_json_serializer.h
new file mode 100644
index 0000000..c92b99a
--- /dev/null
+++ b/src/null_json_serializer.h
@@ -0,0 +1,47 @@
+// Copyright 2020 Google LLC
+//
+// 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
+//
+//     https://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 dap_null_json_serializer_h
+#define dap_null_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+namespace dap {
+namespace json {
+
+struct NullDeserializer : public dap::Deserializer {
+  static NullDeserializer instance;
+
+  bool deserialize(dap::boolean*) const override { return false; }
+  bool deserialize(dap::integer*) const override { return false; }
+  bool deserialize(dap::number*) const override { return false; }
+  bool deserialize(dap::string*) const override { return false; }
+  bool deserialize(dap::object*) const override { return false; }
+  bool deserialize(dap::any*) const override { return false; }
+  size_t count() const override { return 0; }
+  bool array(const std::function<bool(dap::Deserializer*)>&) const override {
+    return false;
+  }
+  bool field(const std::string&,
+             const std::function<bool(dap::Deserializer*)>&) const override {
+    return false;
+  }
+};
+
+}  // namespace json
+}  // namespace dap
+
+#endif  // dap_null_json_serializer_h
diff --git a/src/rapid_json_serializer.cpp b/src/rapid_json_serializer.cpp
new file mode 100644
index 0000000..35cf7e5
--- /dev/null
+++ b/src/rapid_json_serializer.cpp
@@ -0,0 +1,259 @@
+// Copyright 2019 Google LLC
+//
+// 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
+//
+//     https://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 "rapid_json_serializer.h"
+
+#include "null_json_serializer.h"
+
+#include <rapidjson/document.h>
+#include <rapidjson/prettywriter.h>
+
+namespace dap {
+namespace json {
+
+RapidDeserializer::RapidDeserializer(const std::string& str)
+    : doc(new rapidjson::Document()) {
+  doc->Parse(str.c_str());
+}
+
+RapidDeserializer::RapidDeserializer(rapidjson::Value* json) : val(json) {}
+
+RapidDeserializer::~RapidDeserializer() {
+  delete doc;
+}
+
+bool RapidDeserializer::deserialize(dap::boolean* v) const {
+  if (!json()->IsBool()) {
+    return false;
+  }
+  *v = json()->GetBool();
+  return true;
+}
+
+bool RapidDeserializer::deserialize(dap::integer* v) const {
+  if (!json()->IsInt()) {
+    return false;
+  }
+  *v = json()->GetInt();
+  return true;
+}
+
+bool RapidDeserializer::deserialize(dap::number* v) const {
+  if (!json()->IsNumber()) {
+    return false;
+  }
+  *v = json()->GetDouble();
+  return true;
+}
+
+bool RapidDeserializer::deserialize(dap::string* v) const {
+  if (!json()->IsString()) {
+    return false;
+  }
+  *v = json()->GetString();
+  return true;
+}
+
+bool RapidDeserializer::deserialize(dap::object* v) const {
+  v->reserve(json()->MemberCount());
+  for (auto el = json()->MemberBegin(); el != json()->MemberEnd(); el++) {
+    dap::any val;
+    RapidDeserializer d(&(el->value));
+    if (!d.deserialize(&val)) {
+      return false;
+    }
+    (*v)[el->name.GetString()] = val;
+  }
+  return true;
+}
+
+bool RapidDeserializer::deserialize(dap::any* v) const {
+  if (json()->IsBool()) {
+    *v = dap::boolean(json()->GetBool());
+  } else if (json()->IsDouble()) {
+    *v = dap::number(json()->GetDouble());
+  } else if (json()->IsInt()) {
+    *v = dap::integer(json()->GetInt());
+  } else if (json()->IsString()) {
+    *v = dap::string(json()->GetString());
+  } else if (json()->IsNull()) {
+    *v = null();
+  } else {
+    return false;
+  }
+  return true;
+}
+
+size_t RapidDeserializer::count() const {
+  return json()->Size();
+}
+
+bool RapidDeserializer::array(
+    const std::function<bool(dap::Deserializer*)>& cb) const {
+  if (!json()->IsArray()) {
+    return false;
+  }
+  for (uint32_t i = 0; i < json()->Size(); i++) {
+    RapidDeserializer d(&(*json())[i]);
+    if (!cb(&d)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool RapidDeserializer::field(
+    const std::string& name,
+    const std::function<bool(dap::Deserializer*)>& cb) const {
+  if (!json()->IsObject()) {
+    return false;
+  }
+  auto it = json()->FindMember(name.c_str());
+  if (it == json()->MemberEnd()) {
+    return cb(&NullDeserializer::instance);
+  }
+  RapidDeserializer d(&(it->value));
+  return cb(&d);
+}
+
+RapidSerializer::RapidSerializer()
+    : doc(new rapidjson::Document(rapidjson::kObjectType)),
+      allocator(doc->GetAllocator()) {}
+
+RapidSerializer::RapidSerializer(rapidjson::Value* json,
+                                 rapidjson::Document::AllocatorType& allocator)
+    : val(json), allocator(allocator) {}
+
+RapidSerializer::~RapidSerializer() {
+  delete doc;
+}
+
+std::string RapidSerializer::dump() const {
+  rapidjson::StringBuffer sb;
+  rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+  json()->Accept(writer);
+  return sb.GetString();
+}
+
+bool RapidSerializer::serialize(dap::boolean v) {
+  json()->SetBool(v);
+  return true;
+}
+
+bool RapidSerializer::serialize(dap::integer v) {
+  json()->SetInt64(v);
+  return true;
+}
+
+bool RapidSerializer::serialize(dap::number v) {
+  json()->SetDouble(v);
+  return true;
+}
+
+bool RapidSerializer::serialize(const dap::string& v) {
+  json()->SetString(v.data(), static_cast<uint32_t>(v.length()), allocator);
+  return true;
+}
+
+bool RapidSerializer::serialize(const dap::object& v) {
+  if (!json()->IsObject()) {
+    json()->SetObject();
+  }
+  for (auto& it : v) {
+    if (!json()->HasMember(it.first.c_str())) {
+      rapidjson::Value name_value{it.first.c_str(), allocator};
+      json()->AddMember(name_value, rapidjson::Value(), allocator);
+    }
+    rapidjson::Value& member = (*json())[it.first.c_str()];
+    RapidSerializer s(&member, allocator);
+    if (!s.serialize(it.second)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool RapidSerializer::serialize(const dap::any& v) {
+  if (v.is<dap::boolean>()) {
+    json()->SetBool((bool)v.get<dap::boolean>());
+  } else if (v.is<dap::integer>()) {
+    json()->SetInt((int)v.get<dap::integer>());
+  } else if (v.is<dap::number>()) {
+    json()->SetDouble((double)v.get<dap::number>());
+  } else if (v.is<dap::string>()) {
+    auto s = v.get<dap::string>();
+    json()->SetString(s.data(), static_cast<uint32_t>(s.length()), allocator);
+  } else if (v.is<dap::null>()) {
+  } else {
+    return false;
+  }
+
+  return true;
+}
+
+bool RapidSerializer::array(size_t count,
+                            const std::function<bool(dap::Serializer*)>& cb) {
+  if (!json()->IsArray()) {
+    json()->SetArray();
+  }
+
+  while (count > json()->Size()) {
+    json()->PushBack(rapidjson::Value(), allocator);
+  }
+
+  for (uint32_t i = 0; i < count; i++) {
+    RapidSerializer s(&(*json())[i], allocator);
+    if (!cb(&s)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool RapidSerializer::object(
+    const std::function<bool(dap::FieldSerializer*)>& cb) {
+  struct FS : public FieldSerializer {
+    rapidjson::Value* const json;
+    rapidjson::Document::AllocatorType& allocator;
+
+    FS(rapidjson::Value* json, rapidjson::Document::AllocatorType& allocator)
+        : json(json), allocator(allocator) {}
+    bool field(const std::string& name, const SerializeFunc& cb) override {
+      if (!json->HasMember(name.c_str())) {
+        rapidjson::Value name_value{name.c_str(), allocator};
+        json->AddMember(name_value, rapidjson::Value(), allocator);
+      }
+      rapidjson::Value& member = (*json)[name.c_str()];
+      RapidSerializer s(&member, allocator);
+      auto res = cb(&s);
+      if (s.removed) {
+        json->RemoveMember(name.c_str());
+      }
+      return res;
+    }
+  };
+
+  if (!json()->IsObject()) {
+    json()->SetObject();
+  }
+  FS fs{json(), allocator};
+  return cb(&fs);
+}
+
+void RapidSerializer::remove() {
+  removed = true;
+}
+
+}  // namespace json
+}  // namespace dap
diff --git a/src/rapid_json_serializer.h b/src/rapid_json_serializer.h
new file mode 100644
index 0000000..6e83384
--- /dev/null
+++ b/src/rapid_json_serializer.h
@@ -0,0 +1,138 @@
+// Copyright 2019 Google LLC
+//
+// 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
+//
+//     https://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 dap_rapid_json_serializer_h
+#define dap_rapid_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+#include <rapidjson/document.h>
+
+namespace dap {
+namespace json {
+
+struct RapidDeserializer : public dap::Deserializer {
+  explicit RapidDeserializer(const std::string&);
+  ~RapidDeserializer();
+
+  // dap::Deserializer compliance
+  bool deserialize(boolean* v) const override;
+  bool deserialize(integer* v) const override;
+  bool deserialize(number* v) const override;
+  bool deserialize(string* v) const override;
+  bool deserialize(object* v) const override;
+  bool deserialize(any* v) const override;
+  size_t count() const override;
+  bool array(const std::function<bool(dap::Deserializer*)>&) const override;
+  bool field(const std::string& name,
+             const std::function<bool(dap::Deserializer*)>&) const override;
+
+  // Unhide base overloads
+  template <typename T>
+  inline bool field(const std::string& name, T* v) {
+    return dap::Deserializer::field(name, v);
+  }
+
+  template <typename T,
+            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+  inline bool deserialize(T* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool deserialize(dap::array<T>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool deserialize(dap::optional<T>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T0, typename... Types>
+  inline bool deserialize(dap::variant<T0, Types...>* v) const {
+    return dap::Deserializer::deserialize(v);
+  }
+
+  template <typename T>
+  inline bool field(const std::string& name, T* v) const {
+    return dap::Deserializer::deserialize(name, v);
+  }
+
+  inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
+
+ private:
+  RapidDeserializer(rapidjson::Value*);
+  rapidjson::Document* const doc = nullptr;
+  rapidjson::Value* const val = nullptr;
+};
+
+struct RapidSerializer : public dap::Serializer {
+  RapidSerializer();
+  ~RapidSerializer();
+
+  std::string dump() const;
+
+  // dap::Serializer compliance
+  bool serialize(boolean v) override;
+  bool serialize(integer v) override;
+  bool serialize(number v) override;
+  bool serialize(const string& v) override;
+  bool serialize(const dap::object& v) override;
+  bool serialize(const any& v) override;
+  bool array(size_t count,
+             const std::function<bool(dap::Serializer*)>&) override;
+  bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
+  void remove() override;
+
+  // Unhide base overloads
+  template <typename T,
+            typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+  inline bool serialize(const T& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T>
+  inline bool serialize(const dap::array<T>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T>
+  inline bool serialize(const dap::optional<T>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  template <typename T0, typename... Types>
+  inline bool serialize(const dap::variant<T0, Types...>& v) {
+    return dap::Serializer::serialize(v);
+  }
+
+  inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
+
+  inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
+
+ private:
+  RapidSerializer(rapidjson::Value*, rapidjson::Document::AllocatorType&);
+  rapidjson::Document* const doc = nullptr;
+  rapidjson::Value* const val = nullptr;
+  rapidjson::Document::AllocatorType& allocator;
+  bool removed = false;
+};
+
+}  // namespace json
+}  // namespace dap
+
+#endif  // dap_rapid_json_serializer_h
diff --git a/src/socket.cpp b/src/socket.cpp
index 2e54580..998fed9 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -302,7 +302,7 @@
 
       timeval tv;
       tv.tv_sec = microseconds / 1000000;
-      tv.tv_usec = microseconds - (tv.tv_sec * 1000000);
+      tv.tv_usec = microseconds - static_cast<uint32_t>(tv.tv_sec * 1000000);
       res = select(static_cast<int>(socket + 1), nullptr, &fdset, nullptr, &tv);
       if (res > 0 && !errored(socket) && setBlocking(socket, true)) {
         out = shared;
diff --git a/src/typeof.cpp b/src/typeof.cpp
index a5685d3..055421c 100644
--- a/src/typeof.cpp
+++ b/src/typeof.cpp
@@ -130,7 +130,7 @@
 }
 
 void TypeInfo::deleteOnExit(TypeInfo* ti) {
-  return TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti));
+  TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti));
 }
 
 void initialize() {