Split array and string stuff out of type-safety.h.
diff --git a/c++/src/capnproto/generated-header-support.h b/c++/src/capnproto/generated-header-support.h
index d8ec47b..e48bef4 100644
--- a/c++/src/capnproto/generated-header-support.h
+++ b/c++/src/capnproto/generated-header-support.h
@@ -28,6 +28,7 @@
 
 #include "layout.h"
 #include "list.h"
+#include <kj/string.h>
 
 namespace capnproto {
 
diff --git a/c++/src/kj/array.c++ b/c++/src/kj/array.c++
new file mode 100644
index 0000000..aec257a
--- /dev/null
+++ b/c++/src/kj/array.c++
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "array.h"
+
+namespace kj {
+
+}  // namespace kj
diff --git a/c++/src/kj/array.h b/c++/src/kj/array.h
new file mode 100644
index 0000000..b155cac
--- /dev/null
+++ b/c++/src/kj/array.h
@@ -0,0 +1,186 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef KJ_ARRAY_H_
+#define KJ_ARRAY_H_
+
+#include "common.h"
+#include "memory.h"
+#include <string.h>
+
+namespace kj {
+
+// =======================================================================================
+// Array
+
+template <typename T>
+class Array {
+  // An owned array which will automatically be deleted in the destructor.  Can be moved, but not
+  // copied.
+
+public:
+  inline Array(): ptr(nullptr), size_(0) {}
+  inline Array(decltype(nullptr)): ptr(nullptr), size_(0) {}
+  inline Array(Array&& other) noexcept: ptr(other.ptr), size_(other.size_) {
+    other.ptr = nullptr;
+    other.size_ = 0;
+  }
+
+  KJ_DISALLOW_COPY(Array);
+  inline ~Array() noexcept { delete[] ptr; }
+
+  inline operator ArrayPtr<T>() {
+    return ArrayPtr<T>(ptr, size_);
+  }
+  inline operator ArrayPtr<const T>() const {
+    return ArrayPtr<T>(ptr, size_);
+  }
+  inline ArrayPtr<T> asPtr() {
+    return ArrayPtr<T>(ptr, size_);
+  }
+
+  inline size_t size() const { return size_; }
+  inline T& operator[](size_t index) const {
+    KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds Array access.");
+    return ptr[index];
+  }
+
+  inline T* begin() const { return ptr; }
+  inline T* end() const { return ptr + size_; }
+  inline T& front() const { return *ptr; }
+  inline T& back() const { return *(ptr + size_ - 1); }
+
+  inline ArrayPtr<T> slice(size_t start, size_t end) {
+    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
+    return ArrayPtr<T>(ptr + start, end - start);
+  }
+  inline ArrayPtr<const T> slice(size_t start, size_t end) const {
+    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
+    return ArrayPtr<const T>(ptr + start, end - start);
+  }
+
+  inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
+  inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }
+
+  inline Array& operator=(decltype(nullptr)) {
+    delete[] ptr;
+    ptr = nullptr;
+    size_ = 0;
+    return *this;
+  }
+
+  inline Array& operator=(Array&& other) {
+    delete[] ptr;
+    ptr = other.ptr;
+    size_ = other.size_;
+    other.ptr = nullptr;
+    other.size_ = 0;
+    return *this;
+  }
+
+private:
+  T* ptr;
+  size_t size_;
+
+  inline explicit Array(size_t size): ptr(new T[size]), size_(size) {}
+  inline Array(T* ptr, size_t size): ptr(ptr), size_(size) {}
+
+  template <typename U>
+  friend Array<U> newArray(size_t size);
+
+  template <typename U>
+  friend class ArrayBuilder;
+};
+
+template <typename T>
+inline Array<T> newArray(size_t size) {
+  return Array<T>(size);
+}
+
+// =======================================================================================
+// ArrayBuilder
+
+template <typename T>
+class ArrayBuilder {
+  // TODO(cleanup):  This class doesn't work for non-primitive types because Slot is not
+  //   constructable.  Giving Slot a constructor/destructor means arrays of it have to be tagged
+  //   so operator delete can run the destructors.  If we reinterpret_cast the array to an array
+  //   of T and delete it as that type, operator delete gets very upset.
+  //
+  //   Perhaps we should bite the bullet and make the Array family do manual memory allocation,
+  //   bypassing the rather-stupid C++ array new/delete operators which store a redundant copy of
+  //   the size anyway.
+
+  union Slot {
+    T value;
+    char dummy;
+  };
+  static_assert(sizeof(Slot) == sizeof(T), "union is bigger than content?");
+
+public:
+  explicit ArrayBuilder(size_t size): ptr(new Slot[size]), pos(ptr), endPtr(ptr + size) {}
+  ~ArrayBuilder() {
+    for (Slot* p = ptr; p < pos; ++p) {
+      p->value.~T();
+    }
+    delete [] ptr;
+  }
+
+  template <typename... Params>
+  void add(Params&&... params) {
+    KJ_INLINE_DPRECOND(pos < endPtr, "Added too many elements to ArrayBuilder.");
+    new(&pos->value) T(kj::fwd<Params>(params)...);
+    ++pos;
+  }
+
+  template <typename Container>
+  void addAll(Container&& container) {
+    Slot* __restrict__ pos_ = pos;
+    auto i = container.begin();
+    auto end = container.end();
+    while (i != end) {
+      pos_++->value = *i++;
+    }
+    pos = pos_;
+  }
+
+  Array<T> finish() {
+    // We could allow partial builds if Array<T> used a deleter callback, but that would make
+    // Array<T> bigger for no benefit most of the time.
+    KJ_INLINE_DPRECOND(pos == endPtr, "ArrayBuilder::finish() called prematurely.");
+    Array<T> result(reinterpret_cast<T*>(ptr), pos - ptr);
+    ptr = nullptr;
+    pos = nullptr;
+    endPtr = nullptr;
+    return result;
+  }
+
+private:
+  Slot* ptr;
+  Slot* pos;
+  Slot* endPtr;
+};
+
+}  // namespace kj
+
+#endif  // KJ_ARRAY_H_
diff --git a/c++/src/kj/common.h b/c++/src/kj/common.h
index 8dd6686..7353c27 100644
--- a/c++/src/kj/common.h
+++ b/c++/src/kj/common.h
@@ -462,6 +462,63 @@
   friend U* internal::readMaybe(const Maybe<U&>& maybe);
 };
 
+
+// =======================================================================================
+// ArrayPtr
+//
+// So common that we put it in common.h rather than array.h.
+
+template <typename T>
+class ArrayPtr {
+  // A pointer to an array.  Includes a size.  Like any pointer, it doesn't own the target data,
+  // and passing by value only copies the pointer, not the target.
+
+public:
+  inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
+  inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
+  inline constexpr ArrayPtr(T* ptr, size_t size): ptr(ptr), size_(size) {}
+  inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {}
+
+  inline operator ArrayPtr<const T>() {
+    return ArrayPtr<const T>(ptr, size_);
+  }
+
+  inline size_t size() const { return size_; }
+  inline T& operator[](size_t index) const {
+    KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds ArrayPtr access.");
+    return ptr[index];
+  }
+
+  inline T* begin() const { return ptr; }
+  inline T* end() const { return ptr + size_; }
+  inline T& front() const { return *ptr; }
+  inline T& back() const { return *(ptr + size_ - 1); }
+
+  inline ArrayPtr slice(size_t start, size_t end) {
+    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
+    return ArrayPtr(ptr + start, end - start);
+  }
+
+  inline bool operator==(decltype(nullptr)) { return size_ == 0; }
+  inline bool operator!=(decltype(nullptr)) { return size_ != 0; }
+
+private:
+  T* ptr;
+  size_t size_;
+};
+
+template <typename T>
+inline constexpr ArrayPtr<T> arrayPtr(T* ptr, size_t size) {
+  // Use this function to construct ArrayPtrs without writing out the type name.
+  return ArrayPtr<T>(ptr, size);
+}
+
+template <typename T>
+inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
+  // Use this function to construct ArrayPtrs without writing out the type name.
+  return ArrayPtr<T>(begin, end);
+}
+
 // =======================================================================================
 // Upcast/downcast
 
diff --git a/c++/src/kj/exception.h b/c++/src/kj/exception.h
index 99907ff..333691e 100644
--- a/c++/src/kj/exception.h
+++ b/c++/src/kj/exception.h
@@ -25,7 +25,7 @@
 #define KJ_EXCEPTION_H_
 
 #include <exception>
-#include "type-safety.h"
+#include "array.h"
 
 namespace kj {
 
diff --git a/c++/src/kj/io.h b/c++/src/kj/io.h
index 203d4ea..ead1190 100644
--- a/c++/src/kj/io.h
+++ b/c++/src/kj/io.h
@@ -26,7 +26,7 @@
 
 #include <cstddef>
 #include "common.h"
-#include "type-safety.h"
+#include "array.h"
 
 namespace kj {
 
diff --git a/c++/src/kj/logging.c++ b/c++/src/kj/logging.c++
index f968247..fd5df37 100644
--- a/c++/src/kj/logging.c++
+++ b/c++/src/kj/logging.c++
@@ -112,11 +112,11 @@
   }
 
   {
-    ArrayPtr<const char> expected = arrayPtr("expected ");
-    ArrayPtr<const char> codeArray = style == LOG ? nullptr : arrayPtr(code);
-    ArrayPtr<const char> sep = arrayPtr(" = ");
-    ArrayPtr<const char> delim = arrayPtr("; ");
-    ArrayPtr<const char> colon = arrayPtr(": ");
+    ArrayPtr<const char> expected = stringPtr("expected ");
+    ArrayPtr<const char> codeArray = style == LOG ? nullptr : stringPtr(code);
+    ArrayPtr<const char> sep = stringPtr(" = ");
+    ArrayPtr<const char> delim = stringPtr("; ");
+    ArrayPtr<const char> colon = stringPtr(": ");
 
     if (style == ASSERTION && strcmp(code, "false") == 0) {
       // Don't print "expected false", that's silly.
@@ -127,7 +127,7 @@
 #if __USE_GNU
     char buffer[256];
     if (style == SYSCALL) {
-      sysErrorArray = arrayPtr(strerror_r(errorNumber, buffer, sizeof(buffer)));
+      sysErrorArray = stringPtr(strerror_r(errorNumber, buffer, sizeof(buffer)));
     }
 #else
     // TODO(port):  Other unixes should have strerror_r but it may have a different signature.
diff --git a/c++/src/kj/memory.c++ b/c++/src/kj/memory.c++
new file mode 100644
index 0000000..bfc5f17
--- /dev/null
+++ b/c++/src/kj/memory.c++
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "memory.h"
+
+namespace kj {
+
+Disposer::~Disposer() {}
+
+}  // namespace kj
diff --git a/c++/src/kj/memory.h b/c++/src/kj/memory.h
new file mode 100644
index 0000000..f90afa1
--- /dev/null
+++ b/c++/src/kj/memory.h
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef KJ_MEMORY_H_
+#define KJ_MEMORY_H_
+
+#include "common.h"
+
+namespace kj {
+
+// =======================================================================================
+
+class Disposer {
+  // Abstract interface for a thing that disposes of some other object.  Often, it makes sense to
+  // decouple an object from the knowledge of how to dispose of it.
+
+protected:
+  virtual ~Disposer();
+
+public:
+  virtual void dispose(void* interiorPointer) = 0;
+  // Disposes of the object that this Disposer owns, and possibly disposes of the disposer itself.
+  //
+  // Callers must assume that the Disposer itself is no longer valid once this returns -- e.g. it
+  // might delete itself.  Callers must in particular be sure not to call the Disposer again even
+  // when dispose() throws an exception.
+  //
+  // `interiorPointer` points somewhere inside of the object -- NOT necessarily at the beginning,
+  // especially in the presence of multiple inheritance.  Most implementations should ignore the
+  // pointer, though a tricky memory allocator could get away with sharing one Disposer among
+  // multiple objects if it can figure out how to find the beginning of the object given an
+  // arbitrary interior pointer.
+};
+
+// =======================================================================================
+// Own<T> -- An owned pointer.
+
+template <typename T>
+class Own {
+  // A transferrable title to a T.  When an Own<T> goes out of scope, the object's Disposer is
+  // called to dispose of it.  An Own<T> can be efficiently passed by move, without relocating the
+  // underlying object; this transfers ownership.
+  //
+  // This is much like std::unique_ptr, except:
+  // - You cannot release().  An owned object is not necessarily allocated with new (see next
+  //   point), so it would be hard to use release() correctly.
+  // - The deleter is made polymorphic by virtual call rather than by template.  This is a much
+  //   more powerful default -- it allows any random module to decide to use a custom allocator.
+  //   This could be accomplished with unique_ptr by forcing everyone to use e.g.
+  //   std::unique_ptr<T, kj::Disposer&>, but at that point we've lost basically any benefit
+  //   of interoperating with std::unique_ptr anyway.
+
+public:
+  Own(const Own& other) = delete;
+  inline Own(Own&& other) noexcept
+      : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
+  template <typename U>
+  inline Own(Own<U>&& other) noexcept
+      : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
+  inline Own(T* ptr, Disposer* disposer) noexcept: disposer(disposer), ptr(ptr) {}
+
+  ~Own() noexcept { dispose(); }
+
+  inline Own& operator=(Own&& other) {
+    dispose();
+    disposer = other.disposer;
+    ptr = other.ptr;
+    other.ptr = nullptr;
+    return *this;
+  }
+
+  inline T* operator->() { return ptr; }
+  inline const T* operator->() const { return ptr; }
+  inline T& operator*() { return *ptr; }
+  inline const T& operator*() const { return *ptr; }
+  inline T* get() { return ptr; }
+  inline const T* get() const { return ptr; }
+  inline operator T*() { return ptr; }
+  inline operator const T*() const { return ptr; }
+
+private:
+  Disposer* disposer;  // Only valid if ptr != nullptr.
+  T* ptr;
+
+  inline void dispose() {
+    // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
+    // dispose again.
+    void* ptrCopy = ptr;
+    if (ptrCopy != nullptr) {
+      ptr = nullptr;
+      disposer->dispose(ptrCopy);
+    }
+  }
+};
+
+namespace internal {
+
+template <typename T>
+class HeapValue final: public Disposer {
+public:
+  template <typename... Params>
+  inline HeapValue(Params&&... params): value(kj::fwd<Params>(params)...) {}
+
+  virtual void dispose(void*) override { delete this; }
+
+  T value;
+};
+
+}  // namespace internal
+
+template <typename T, typename... Params>
+Own<T> heap(Params&&... params) {
+  // heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor.  The
+  // exact heap implementation is unspecified -- for now it is operator new, but you should not
+  // assume anything.
+
+  auto result = new internal::HeapValue<T>(kj::fwd<Params>(params)...);
+  return Own<T>(&result->value, result);
+}
+
+}  // namespace kj
+
+#endif  // KJ_MEMORY_H_
diff --git a/c++/src/kj/string.c++ b/c++/src/kj/string.c++
new file mode 100644
index 0000000..88dcf37
--- /dev/null
+++ b/c++/src/kj/string.c++
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "string.h"
+
+namespace kj {
+
+String::String(const char* value): content(newArray<char>(strlen(value) + 1)) {
+  strcpy(content.begin(), value);
+}
+
+String::String(const char* value, size_t length): content(newArray<char>(length + 1)) {
+  memcpy(content.begin(), value, length);
+  content[length] = '\0';
+}
+
+}  // namespace kj
diff --git a/c++/src/kj/string.h b/c++/src/kj/string.h
new file mode 100644
index 0000000..1be15a6
--- /dev/null
+++ b/c++/src/kj/string.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef KJ_STRING_H_
+#define KJ_STRING_H_
+
+#include "array.h"
+#include <string.h>
+
+namespace kj {
+
+inline ArrayPtr<const char> stringPtr(const char* text) {
+  return arrayPtr(text, strlen(text));
+}
+
+// =======================================================================================
+// String -- Just a NUL-terminated Array<char>.
+
+class String {
+public:
+  String() = default;
+  String(const char* value);
+  String(const char* value, size_t length);
+
+  inline ArrayPtr<char> asArray();
+  inline ArrayPtr<const char> asArray() const;
+  inline const char* cStr() const { return content == nullptr ? "" : content.begin(); }
+
+  inline size_t size() const { return content == nullptr ? 0 : content.size() - 1; }
+
+  inline char* begin() { return content == nullptr ? nullptr : content.begin(); }
+  inline char* end() { return content == nullptr ? nullptr : content.end() - 1; }
+  inline const char* begin() const { return content == nullptr ? nullptr : content.begin(); }
+  inline const char* end() const { return content == nullptr ? nullptr : content.end() - 1; }
+
+private:
+  Array<char> content;
+};
+
+inline ArrayPtr<char> String::asArray() {
+  return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
+}
+inline ArrayPtr<const char> String::asArray() const {
+  return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
+}
+
+}  // namespace kj
+
+#endif  // KJ_STRING_H_
diff --git a/c++/src/kj/type-safety.c++ b/c++/src/kj/type-safety.c++
index a874829..812c8bb 100644
--- a/c++/src/kj/type-safety.c++
+++ b/c++/src/kj/type-safety.c++
@@ -25,15 +25,4 @@
 
 namespace kj {
 
-Disposer::~Disposer() {}
-
-String::String(const char* value): content(newArray<char>(strlen(value) + 1)) {
-  strcpy(content.begin(), value);
-}
-
-String::String(const char* value, size_t length): content(newArray<char>(length + 1)) {
-  memcpy(content.begin(), value, length);
-  content[length] = '\0';
-}
-
 }  // namespace kj
diff --git a/c++/src/kj/type-safety.h b/c++/src/kj/type-safety.h
index b670c6c..effef11 100644
--- a/c++/src/kj/type-safety.h
+++ b/c++/src/kj/type-safety.h
@@ -35,349 +35,6 @@
 namespace kj {
 
 // =======================================================================================
-// Own<T> -- An owned pointer.
-
-class Disposer {
-  // Abstract interface for a thing that disposes of some other object.  Often, it makes sense to
-  // decouple an object from the knowledge of how to dispose of it.
-
-protected:
-  virtual ~Disposer();
-
-public:
-  virtual void dispose(void* interiorPointer) = 0;
-  // Disposes of the object that this Disposer owns, and possibly disposes of the disposer itself.
-  //
-  // Callers must assume that the Disposer itself is no longer valid once this returns -- e.g. it
-  // might delete itself.  Callers must in particular be sure not to call the Disposer again even
-  // when dispose() throws an exception.
-  //
-  // `interiorPointer` points somewhere inside of the object -- NOT necessarily at the beginning,
-  // especially in the presence of multiple inheritance.  Most implementations should ignore the
-  // pointer, though a tricky memory allocator could get away with sharing one Disposer among
-  // multiple objects if it can figure out how to find the beginning of the object given an
-  // arbitrary interior pointer.
-};
-
-template <typename T>
-class Own {
-  // A transferrable title to a T.  When an Own<T> goes out of scope, the object's Disposer is
-  // called to dispose of it.  An Own<T> can be efficiently passed by move, without relocating the
-  // underlying object; this transfers ownership.
-  //
-  // This is much like std::unique_ptr, except:
-  // - You cannot release().  An owned object is not necessarily allocated with new (see next
-  //   point), so it would be hard to use release() correctly.
-  // - The deleter is made polymorphic by virtual call rather than by template.  This is a much
-  //   more powerful default -- it allows any random module to decide to use a custom allocator.
-  //   This could be accomplished with unique_ptr by forcing everyone to use e.g.
-  //   std::unique_ptr<T, kj::Disposer&>, but at that point we've lost basically any benefit
-  //   of interoperating with std::unique_ptr anyway.
-
-public:
-  Own(const Own& other) = delete;
-  inline Own(Own&& other) noexcept
-      : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
-  template <typename U>
-  inline Own(Own<U>&& other) noexcept
-      : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
-  inline Own(T* ptr, Disposer* disposer) noexcept: disposer(disposer), ptr(ptr) {}
-
-  ~Own() noexcept { dispose(); }
-
-  inline Own& operator=(Own&& other) {
-    dispose();
-    disposer = other.disposer;
-    ptr = other.ptr;
-    other.ptr = nullptr;
-    return *this;
-  }
-
-  inline T* operator->() { return ptr; }
-  inline const T* operator->() const { return ptr; }
-  inline T& operator*() { return *ptr; }
-  inline const T& operator*() const { return *ptr; }
-  inline T* get() { return ptr; }
-  inline const T* get() const { return ptr; }
-  inline operator T*() { return ptr; }
-  inline operator const T*() const { return ptr; }
-
-private:
-  Disposer* disposer;  // Only valid if ptr != nullptr.
-  T* ptr;
-
-  inline void dispose() {
-    // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
-    // dispose again.
-    void* ptrCopy = ptr;
-    if (ptrCopy != nullptr) {
-      ptr = nullptr;
-      disposer->dispose(ptrCopy);
-    }
-  }
-};
-
-namespace internal {
-
-template <typename T>
-class HeapValue final: public Disposer {
-public:
-  template <typename... Params>
-  inline HeapValue(Params&&... params): value(kj::fwd<Params>(params)...) {}
-
-  virtual void dispose(void*) override { delete this; }
-
-  T value;
-};
-
-}  // namespace internal
-
-template <typename T, typename... Params>
-Own<T> heap(Params&&... params) {
-  // heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor.  The
-  // exact heap implementation is unspecified -- for now it is operator new, but you should not
-  // assume anything.
-
-  auto result = new internal::HeapValue<T>(kj::fwd<Params>(params)...);
-  return Own<T>(&result->value, result);
-}
-
-// =======================================================================================
-// ArrayPtr
-
-template <typename T>
-class ArrayPtr {
-  // A pointer to an array.  Includes a size.  Like any pointer, it doesn't own the target data,
-  // and passing by value only copies the pointer, not the target.
-
-public:
-  inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
-  inline constexpr ArrayPtr(std::nullptr_t): ptr(nullptr), size_(0) {}
-  inline constexpr ArrayPtr(T* ptr, std::size_t size): ptr(ptr), size_(size) {}
-  inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {}
-
-  inline operator ArrayPtr<const T>() {
-    return ArrayPtr<const T>(ptr, size_);
-  }
-
-  inline std::size_t size() const { return size_; }
-  inline T& operator[](std::size_t index) const {
-    KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds ArrayPtr access.");
-    return ptr[index];
-  }
-
-  inline T* begin() const { return ptr; }
-  inline T* end() const { return ptr + size_; }
-  inline T& front() const { return *ptr; }
-  inline T& back() const { return *(ptr + size_ - 1); }
-
-  inline ArrayPtr slice(size_t start, size_t end) {
-    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
-    return ArrayPtr(ptr + start, end - start);
-  }
-
-  inline bool operator==(std::nullptr_t) { return size_ == 0; }
-  inline bool operator!=(std::nullptr_t) { return size_ != 0; }
-
-private:
-  T* ptr;
-  std::size_t size_;
-};
-
-template <typename T>
-inline constexpr ArrayPtr<T> arrayPtr(T* ptr, size_t size) {
-  // Use this function to construct ArrayPtrs without writing out the type name.
-  return ArrayPtr<T>(ptr, size);
-}
-
-template <typename T>
-inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
-  // Use this function to construct ArrayPtrs without writing out the type name.
-  return ArrayPtr<T>(begin, end);
-}
-
-inline ArrayPtr<const char> arrayPtr(const char* s) {
-  // Use this function to construct an ArrayPtr from a NUL-terminated string, especially a literal.
-  return arrayPtr(s, strlen(s));
-}
-
-template <typename T>
-class Array {
-  // An owned array which will automatically be deleted in the destructor.  Can be moved, but not
-  // copied.
-
-public:
-  inline Array(): ptr(nullptr), size_(0) {}
-  inline Array(std::nullptr_t): ptr(nullptr), size_(0) {}
-  inline Array(Array&& other) noexcept: ptr(other.ptr), size_(other.size_) {
-    other.ptr = nullptr;
-    other.size_ = 0;
-  }
-
-  KJ_DISALLOW_COPY(Array);
-  inline ~Array() noexcept { delete[] ptr; }
-
-  inline operator ArrayPtr<T>() {
-    return ArrayPtr<T>(ptr, size_);
-  }
-  inline operator ArrayPtr<const T>() const {
-    return ArrayPtr<T>(ptr, size_);
-  }
-  inline ArrayPtr<T> asPtr() {
-    return ArrayPtr<T>(ptr, size_);
-  }
-
-  inline std::size_t size() const { return size_; }
-  inline T& operator[](std::size_t index) const {
-    KJ_INLINE_DPRECOND(index < size_, "Out-of-bounds Array access.");
-    return ptr[index];
-  }
-
-  inline T* begin() const { return ptr; }
-  inline T* end() const { return ptr + size_; }
-  inline T& front() const { return *ptr; }
-  inline T& back() const { return *(ptr + size_ - 1); }
-
-  inline ArrayPtr<T> slice(size_t start, size_t end) {
-    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
-    return ArrayPtr<T>(ptr + start, end - start);
-  }
-  inline ArrayPtr<const T> slice(size_t start, size_t end) const {
-    KJ_INLINE_DPRECOND(start <= end && end <= size_, "Out-of-bounds Array::slice().");
-    return ArrayPtr<const T>(ptr + start, end - start);
-  }
-
-  inline bool operator==(std::nullptr_t) const { return size_ == 0; }
-  inline bool operator!=(std::nullptr_t) const { return size_ != 0; }
-
-  inline Array& operator=(std::nullptr_t) {
-    delete[] ptr;
-    ptr = nullptr;
-    size_ = 0;
-    return *this;
-  }
-
-  inline Array& operator=(Array&& other) {
-    delete[] ptr;
-    ptr = other.ptr;
-    size_ = other.size_;
-    other.ptr = nullptr;
-    other.size_ = 0;
-    return *this;
-  }
-
-private:
-  T* ptr;
-  size_t size_;
-
-  inline explicit Array(std::size_t size): ptr(new T[size]), size_(size) {}
-  inline Array(T* ptr, size_t size): ptr(ptr), size_(size) {}
-
-  template <typename U>
-  friend Array<U> newArray(size_t size);
-
-  template <typename U>
-  friend class ArrayBuilder;
-};
-
-template <typename T>
-inline Array<T> newArray(size_t size) {
-  return Array<T>(size);
-}
-
-template <typename T>
-class ArrayBuilder {
-  // TODO(cleanup):  This class doesn't work for non-primitive types because Slot is not
-  //   constructable.  Giving Slot a constructor/destructor means arrays of it have to be tagged
-  //   so operator delete can run the destructors.  If we reinterpret_cast the array to an array
-  //   of T and delete it as that type, operator delete gets very upset.
-  //
-  //   Perhaps we should bite the bullet and make the Array family do manual memory allocation,
-  //   bypassing the rather-stupid C++ array new/delete operators which store a redundant copy of
-  //   the size anyway.
-
-  union Slot {
-    T value;
-    char dummy;
-  };
-  static_assert(sizeof(Slot) == sizeof(T), "union is bigger than content?");
-
-public:
-  explicit ArrayBuilder(size_t size): ptr(new Slot[size]), pos(ptr), endPtr(ptr + size) {}
-  ~ArrayBuilder() {
-    for (Slot* p = ptr; p < pos; ++p) {
-      p->value.~T();
-    }
-    delete [] ptr;
-  }
-
-  template <typename... Params>
-  void add(Params&&... params) {
-    KJ_INLINE_DPRECOND(pos < endPtr, "Added too many elements to ArrayBuilder.");
-    new(&pos->value) T(kj::fwd<Params>(params)...);
-    ++pos;
-  }
-
-  template <typename Container>
-  void addAll(Container&& container) {
-    Slot* __restrict__ pos_ = pos;
-    auto i = container.begin();
-    auto end = container.end();
-    while (i != end) {
-      pos_++->value = *i++;
-    }
-    pos = pos_;
-  }
-
-  Array<T> finish() {
-    // We could allow partial builds if Array<T> used a deleter callback, but that would make
-    // Array<T> bigger for no benefit most of the time.
-    KJ_INLINE_DPRECOND(pos == endPtr, "ArrayBuilder::finish() called prematurely.");
-    Array<T> result(reinterpret_cast<T*>(ptr), pos - ptr);
-    ptr = nullptr;
-    pos = nullptr;
-    endPtr = nullptr;
-    return result;
-  }
-
-private:
-  Slot* ptr;
-  Slot* pos;
-  Slot* endPtr;
-};
-
-// =======================================================================================
-// String -- Just a NUL-terminated Array<char>.
-
-class String {
-public:
-  String() = default;
-  String(const char* value);
-  String(const char* value, size_t length);
-
-  inline ArrayPtr<char> asArray();
-  inline ArrayPtr<const char> asArray() const;
-  inline const char* cStr() const { return content == nullptr ? "" : content.begin(); }
-
-  inline size_t size() const { return content == nullptr ? 0 : content.size() - 1; }
-
-  inline char* begin() { return content == nullptr ? nullptr : content.begin(); }
-  inline char* end() { return content == nullptr ? nullptr : content.end() - 1; }
-  inline const char* begin() const { return content == nullptr ? nullptr : content.begin(); }
-  inline const char* end() const { return content == nullptr ? nullptr : content.end() - 1; }
-
-private:
-  Array<char> content;
-};
-
-inline ArrayPtr<char> String::asArray() {
-  return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
-}
-inline ArrayPtr<const char> String::asArray() const {
-  return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1);
-}
-
-// =======================================================================================
 // IDs
 
 template <typename UnderlyingType, typename Label>
diff --git a/c++/src/kj/util.h b/c++/src/kj/util.h
index 046816f..1ca5021 100644
--- a/c++/src/kj/util.h
+++ b/c++/src/kj/util.h
@@ -27,7 +27,8 @@
 #include <initializer_list>
 #include <utility>
 #include <type_traits>
-#include "type-safety.h"
+#include "array.h"
+#include "string.h"
 #include <string.h>
 
 namespace kj {