Remove obsolete libcppbor code from identity module

Change-Id: I618efbf072000ea250c14ec94ddd16550baa7b01
Test: TH
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 4e3d1f7..3096fe5 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -65,57 +65,3 @@
     ],
     test_suites: ["general-tests"],
 }
-
-// --
-
-cc_library {
-    name: "libcppbor",
-    vendor_available: true,
-    host_supported: true,
-    srcs: [
-        "src/cppbor.cpp",
-        "src/cppbor_parse.cpp",
-    ],
-    export_include_dirs: [
-        "include/cppbor",
-    ],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_test {
-    name: "cppbor_test",
-    tidy_timeout_srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    shared_libs: [
-        "libcppbor_external",
-        "libbase",
-    ],
-    static_libs: [
-        "libgmock",
-    ],
-    test_suites: ["general-tests"],
-}
-
-cc_test_host {
-    name: "cppbor_host_test",
-    tidy_timeout_srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    srcs: [
-        "tests/cppbor_test.cpp",
-    ],
-    shared_libs: [
-        "libcppbor_external",
-        "libbase",
-    ],
-    static_libs: [
-        "libgmock",
-    ],
-    test_suites: ["general-tests"],
-}
diff --git a/identity/support/include/cppbor/README.md b/identity/support/include/cppbor/README.md
deleted file mode 100644
index 723bfcf..0000000
--- a/identity/support/include/cppbor/README.md
+++ /dev/null
@@ -1,216 +0,0 @@
-CppBor: A Modern C++ CBOR Parser and Generator
-==============================================
-
-CppBor provides a natural and easy-to-use syntax for constructing and
-parsing CBOR messages.  It does not (yet) support all features of
-CBOR, nor (yet) support validation against CDDL schemata, though both
-are planned.  CBOR features that aren't supported include:
-
-* Indefinite length values
-* Semantic tagging
-* Floating point
-
-CppBor requires C++-17.
-
-## CBOR representation
-
-CppBor represents CBOR data items as instances of the `Item` class or,
-more precisely, as instances of subclasses of `Item`, since `Item` is a
-pure interface.  The subclasses of `Item` correspond almost one-to-one
-with CBOR major types, and are named to match the CDDL names to which
-they correspond.  They are:
-
-* `Uint` corresponds to major type 0, and can hold unsigned integers
-  up through (2^64 - 1).
-* `Nint` corresponds to major type 1.  It can only hold values from -1
-  to -(2^63 - 1), since it's internal representation is an int64_t.
-  This can be fixed, but it seems unlikely that applications will need
-  the omitted range from -(2^63) to (2^64 - 1), since it's
-  inconvenient to represent them in many programming languages.
-* `Int` is an abstract base of `Uint` and `Nint` that facilitates
-  working with all signed integers representable with int64_t.
-* `Bstr` corresponds to major type 2, a byte string.
-* `Tstr` corresponds to major type 3, a text string.
-* `Array` corresponds to major type 4, an Array.  It holds a
-  variable-length array of `Item`s.
-* `Map` corresponds to major type 5, a Map.  It holds a
-  variable-length array of pairs of `Item`s.
-* `Simple` corresponds to major type 7.  It's an abstract class since
-  items require more specific type.
-* `Bool` is the only currently-implemented subclass of `Simple`.
-
-Note that major type 6, semantic tag, is not yet implemented.
-
-In practice, users of CppBor will rarely use most of these classes
-when generating CBOR encodings.  This is because CppBor provides
-straightforward conversions from the obvious normal C++ types.
-Specifically, the following conversions are provided in appropriate
-contexts:
-
-* Signed and unsigned integers convert to `Uint` or `Nint`, as
-  appropriate.
-* `std::string`, `std::string_view`, `const char*` and
-  `std::pair<char iterator, char iterator>` convert to `Tstr`.
-* `std::vector<uint8_t>`, `std::pair<uint8_t iterator, uint8_t
-  iterator>` and `std::pair<uint8_t*, size_t>` convert to `Bstr`.
-* `bool` converts to `Bool`.
-
-## CBOR generation
-
-### Complete tree generation
-
-The set of `encode` methods in `Item` provide the interface for
-producing encoded CBOR.  The basic process for "complete tree"
-generation (as opposed to "incremental" generation, which is discussed
-below) is to construct an `Item` which models the data to be encoded,
-and then call one of the `encode` methods, whichever is convenient for
-the encoding destination.  A trivial example:
-
-```
-cppbor::Uint val(0);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-    It's relatively rare that single values are encoded as above.  More often, the
-    "root" data item will be an `Array` or `Map` which contains a more complex structure.For example
-    :
-
-``` using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec =  // ...
-    Map val("key1", Array(Map("key_a", 99 "key_b", vec), "foo"), "key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-This creates a map with two entries, with `Tstr` keys "Outer1" and
-"Outer2", respectively.  The "Outer1" entry has as its value an
-`Array` containing a `Map` and a `Tstr`.  The "Outer2" entry has a
-`Bool` value.
-
-This example demonstrates how automatic conversion of C++ types to
-CppBor `Item` subclass instances is done.  Where the caller provides a
-C++ or C string, a `Tstr` entry is added.  Where the caller provides
-an integer literal or variable, a `Uint` or `Nint` is added, depending
-on whether the value is positive or negative.
-
-As an alternative, a more fluent-style API is provided for building up
-structures.  For example:
-
-```
-using cppbor::Map;
-using cppbor::Array;
-
-std::vector<uint8_t> vec =  // ...
-    Map val();
-val.add("key1", Array().add(Map().add("key_a", 99).add("key_b", vec)).add("foo")).add("key2", true);
-std::vector<uint8_t> encoding = val.encode();
-```
-
-    An advantage of this interface over the constructor -
-    based creation approach above is that it need not be done all at once
-        .The `add` methods return a reference to the object added to to allow calls to be chained,
-    but chaining is not necessary; calls can be made
-sequentially, as the data to add is available.
-
-#### `encode` methods
-
-There are several variations of `Item::encode`, all of which
-accomplish the same task but output the encoded data in different
-ways, and with somewhat different performance characteristics.  The
-provided options are:
-
-* `bool encode(uint8\_t** pos, const uint8\_t* end)` encodes into the
-  buffer referenced by the range [`*pos`, end).  `*pos` is moved.  If
-  the encoding runs out of buffer space before finishing, the method
-  returns false.  This is the most efficient way to encode, into an
-  already-allocated buffer.
-* `void encode(EncodeCallback encodeCallback)` calls `encodeCallback`
-  for each encoded byte.  It's the responsibility of the implementor
-  of the callback to behave safely in the event that the output buffer
-  (if applicable) is exhausted.  This is less efficient than the prior
-  method because it imposes an additional function call for each byte.
-* `template </*...*/> void encode(OutputIterator i)`
-  encodes into the provided iterator.  SFINAE ensures that the
-  template doesn't match for non-iterators.  The implementation
-  actually uses the callback-based method, plus has whatever overhead
-  the iterator adds.
-* `std::vector<uint8_t> encode()` creates a new std::vector, reserves
-  sufficient capacity to hold the encoding, and inserts the encoded
-  bytes with a std::pushback_iterator and the previous method.
-* `std::string toString()` does the same as the previous method, but
-  returns a string instead of a vector.
-
-### Incremental generation
-
-Incremental generation requires deeper understanding of CBOR, because
-the library can't do as much to ensure that the output is valid.  The
-basic tool for intcremental generation is the `encodeHeader`
-function.  There are two variations, one which writes into a buffer,
-and one which uses a callback.  Both simply write out the bytes of a
-header.  To construct the same map as in the above examples,
-incrementally, one might write:
-
-```
-using namespace cppbor;  // For example brevity
-
-std::vector encoding;
-auto iter = std::back_inserter(result);
-encodeHeader(MAP, 2 /* # of map entries */, iter);
-std::string s = "key1";
-encodeHeader(TSTR, s.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(ARRAY, 2 /* # of array entries */, iter);
-Map().add("key_a", 99).add("key_b", vec).encode(iter)
-s = "foo";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-s = "key2";
-encodeHeader(TSTR, foo.size(), iter);
-std::copy(s.begin(), s.end(), iter);
-encodeHeader(SIMPLE, TRUE, iter);
-```
-
-As the above example demonstrates, the styles can be mixed -- Note the
-creation and encoding of the inner Map using the fluent style.
-
-## Parsing
-
-CppBor also supports parsing of encoded CBOR data, with the same
-feature set as encoding.  There are two basic approaches to parsing,
-"full" and "stream"
-
-### Full parsing
-
-Full parsing means completely parsing a (possibly-compound) data
-item from a byte buffer.  The `parse` functions that do not take a
-`ParseClient` pointer do this.  They return a `ParseResult` which is a
-tuple of three values:
-
-* std::unique_ptr<Item> that points to the parsed item, or is nullptr
-  if there was a parse error.
-* const uint8_t* that points to the byte after the end of the decoded
-  item, or to the first unparseable byte in the event of an error.
-* std::string that is empty on success or contains an error message if
-  a parse error occurred.
-
-Assuming a successful parse, you can then use `Item::type()` to
-discover the type of the parsed item (e.g. MAP), and then use the
-appropriate `Item::as*()` method (e.g. `Item::asMap()`) to get a
-pointer to an interface which allows you to retrieve specific values.
-
-### Stream parsing
-
-Stream parsing is more complex, but more flexible.  To use
-StreamParsing, you must create your own subclass of `ParseClient` and
-call one of the `parse` functions that accepts it.  See the
-`ParseClient` methods docstrings for details.
-
-One unusual feature of stream parsing is that the `ParseClient`
-callback methods not only provide the parsed Item, but also pointers
-to the portion of the buffer that encode that Item.  This is useful
-if, for example, you want to find an element inside of a structure,
-and then copy the encoding of that sub-structure, without bothering to
-parse the rest.
-
-The full parser is implemented with the stream parser.
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
deleted file mode 100644
index af5d82e..0000000
--- a/identity/support/include/cppbor/cppbor.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <numeric>
-#include <string>
-#include <vector>
-
-namespace cppbor {
-
-enum MajorType : uint8_t {
-    UINT = 0 << 5,
-    NINT = 1 << 5,
-    BSTR = 2 << 5,
-    TSTR = 3 << 5,
-    ARRAY = 4 << 5,
-    MAP = 5 << 5,
-    SEMANTIC = 6 << 5,
-    SIMPLE = 7 << 5,
-};
-
-enum SimpleType {
-    BOOLEAN,
-    NULL_T,  // Only two supported, as yet.
-};
-
-enum SpecialAddlInfoValues : uint8_t {
-    FALSE = 20,
-    TRUE = 21,
-    NULL_V = 22,
-    ONE_BYTE_LENGTH = 24,
-    TWO_BYTE_LENGTH = 25,
-    FOUR_BYTE_LENGTH = 26,
-    EIGHT_BYTE_LENGTH = 27,
-};
-
-class Item;
-class Uint;
-class Nint;
-class Int;
-class Tstr;
-class Bstr;
-class Simple;
-class Bool;
-class Array;
-class Map;
-class Null;
-class Semantic;
-
-/**
- * Returns the size of a CBOR header that contains the additional info value addlInfo.
- */
-size_t headerSize(uint64_t addlInfo);
-
-/**
- * Encodes a CBOR header with the specified type and additional info into the range [pos, end).
- * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space
- * to write the header.
- */
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end);
-
-using EncodeCallback = std::function<void(uint8_t)>;
-
-/**
- * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to
- * encodeCallback.
- */
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback);
-
-/**
- * Encodes a CBOR header with the specified type and additional info, writing each byte to the
- * provided OutputIterator.
- */
-template <typename OutputIterator,
-          typename = std::enable_if_t<std::is_base_of_v<
-                  std::output_iterator_tag,
-                  typename std::iterator_traits<OutputIterator>::iterator_category>>>
-void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) {
-    return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; });
-}
-
-/**
- * Item represents a CBOR-encodeable data item.  Item is an abstract interface with a set of virtual
- * methods that allow encoding of the item or conversion to the appropriate derived type.
- */
-class Item {
-  public:
-    virtual ~Item() {}
-
-    /**
-     * Returns the CBOR type of the item.
-     */
-    virtual MajorType type() const = 0;
-
-    // These methods safely downcast an Item to the appropriate subclass.
-    virtual const Int* asInt() const { return nullptr; }
-    virtual const Uint* asUint() const { return nullptr; }
-    virtual const Nint* asNint() const { return nullptr; }
-    virtual const Tstr* asTstr() const { return nullptr; }
-    virtual const Bstr* asBstr() const { return nullptr; }
-    virtual const Simple* asSimple() const { return nullptr; }
-    virtual const Map* asMap() const { return nullptr; }
-    virtual const Array* asArray() const { return nullptr; }
-    virtual const Semantic* asSemantic() const { return nullptr; }
-
-    /**
-     * Returns true if this is a "compound" item, i.e. one that contains one or more other items.
-     */
-    virtual bool isCompound() const { return false; }
-
-    bool operator==(const Item& other) const&;
-    bool operator!=(const Item& other) const& { return !(*this == other); }
-
-    /**
-     * Returns the number of bytes required to encode this Item into CBOR.  Note that if this is a
-     * complex Item, calling this method will require walking the whole tree.
-     */
-    virtual size_t encodedSize() const = 0;
-
-    /**
-     * Encodes the Item into buffer referenced by range [*pos, end).  Returns a pointer to one past
-     * the last position written.  Returns nullptr if there isn't enough space to encode.
-     */
-    virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0;
-
-    /**
-     * Encodes the Item by passing each encoded byte to encodeCallback.
-     */
-    virtual void encode(EncodeCallback encodeCallback) const = 0;
-
-    /**
-     * Clones the Item
-     */
-    virtual std::unique_ptr<Item> clone() const = 0;
-
-    /**
-     * Encodes the Item into the provided OutputIterator.
-     */
-    template <typename OutputIterator,
-              typename = typename std::iterator_traits<OutputIterator>::iterator_category>
-    void encode(OutputIterator i) const {
-        return encode([&](uint8_t v) { *i++ = v; });
-    }
-
-    /**
-     * Encodes the Item into a new std::vector<uint8_t>.
-     */
-    std::vector<uint8_t> encode() const {
-        std::vector<uint8_t> retval;
-        retval.reserve(encodedSize());
-        encode(std::back_inserter(retval));
-        return retval;
-    }
-
-    /**
-     * Encodes the Item into a new std::string.
-     */
-    std::string toString() const {
-        std::string retval;
-        retval.reserve(encodedSize());
-        encode([&](uint8_t v) { retval.push_back(v); });
-        return retval;
-    }
-
-    /**
-     * Encodes only the header of the Item.
-     */
-    inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const {
-        return ::cppbor::encodeHeader(type(), addlInfo, pos, end);
-    }
-
-    /**
-     * Encodes only the header of the Item.
-     */
-    inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const {
-        ::cppbor::encodeHeader(type(), addlInfo, encodeCallback);
-    }
-};
-
-/**
- * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about
- * the sign.
- */
-class Int : public Item {
-  public:
-    bool operator==(const Int& other) const& { return value() == other.value(); }
-
-    virtual int64_t value() const = 0;
-
-    const Int* asInt() const override { return this; }
-};
-
-/**
- * Uint is a concrete Item that implements CBOR major type 0.
- */
-class Uint : public Int {
-  public:
-    static constexpr MajorType kMajorType = UINT;
-
-    explicit Uint(uint64_t v) : mValue(v) {}
-
-    bool operator==(const Uint& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Uint* asUint() const override { return this; }
-
-    size_t encodedSize() const override { return headerSize(mValue); }
-
-    int64_t value() const override { return mValue; }
-    uint64_t unsignedValue() const { return mValue; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(mValue, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue, encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); }
-
-  private:
-    uint64_t mValue;
-};
-
-/**
- * Nint is a concrete Item that implements CBOR major type 1.
-
- * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only
- * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1].  It cannot
- * express values in the range [std::numeric_limits<int64_t>::min() - 1,
- * -std::numeric_limits<uint64_t>::max()].
- */
-class Nint : public Int {
-  public:
-    static constexpr MajorType kMajorType = NINT;
-
-    explicit Nint(int64_t v);
-
-    bool operator==(const Nint& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Nint* asNint() const override { return this; }
-    size_t encodedSize() const override { return headerSize(addlInfo()); }
-
-    int64_t value() const override { return mValue; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(addlInfo(), pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(addlInfo(), encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
-
-  private:
-    uint64_t addlInfo() const { return -1LL - mValue; }
-
-    int64_t mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 2.
- */
-class Bstr : public Item {
-  public:
-    static constexpr MajorType kMajorType = BSTR;
-
-    // Construct from a vector
-    explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {}
-
-    // Construct from a string
-    explicit Bstr(const std::string& v)
-        : mValue(reinterpret_cast<const uint8_t*>(v.data()),
-                 reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {}
-
-    // Construct from a pointer/size pair
-    explicit Bstr(const std::pair<const uint8_t*, size_t>& buf)
-        : mValue(buf.first, buf.first + buf.second) {}
-
-    // Construct from a pair of iterators
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
-    // Construct from an iterator range.
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    Bstr(I1 begin, I2 end) : mValue(begin, end) {}
-
-    bool operator==(const Bstr& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Bstr* asBstr() const override { return this; }
-    size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue.size(), encodeCallback);
-        encodeValue(encodeCallback);
-    }
-
-    const std::vector<uint8_t>& value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); }
-
-  private:
-    void encodeValue(EncodeCallback encodeCallback) const;
-
-    std::vector<uint8_t> mValue;
-};
-
-/**
- * Bstr is a concrete Item that implements major type 3.
- */
-class Tstr : public Item {
-  public:
-    static constexpr MajorType kMajorType = TSTR;
-
-    // Construct from a string
-    explicit Tstr(std::string v) : mValue(std::move(v)) {}
-
-    // Construct from a string_view
-    explicit Tstr(const std::string_view& v) : mValue(v) {}
-
-    // Construct from a C string
-    explicit Tstr(const char* v) : mValue(std::string(v)) {}
-
-    // Construct from a pair of iterators
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
-
-    // Construct from an iterator range
-    template <typename I1, typename I2,
-              typename = typename std::iterator_traits<I1>::iterator_category,
-              typename = typename std::iterator_traits<I2>::iterator_category>
-    Tstr(I1 begin, I2 end) : mValue(begin, end) {}
-
-    bool operator==(const Tstr& other) const& { return mValue == other.mValue; }
-
-    MajorType type() const override { return kMajorType; }
-    const Tstr* asTstr() const override { return this; }
-    size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue.size(), encodeCallback);
-        encodeValue(encodeCallback);
-    }
-
-    const std::string& value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); }
-
-  private:
-    void encodeValue(EncodeCallback encodeCallback) const;
-
-    std::string mValue;
-};
-
-/**
- * CompoundItem is an abstract Item that provides common functionality for Items that contain other
- * items, i.e. Arrays (CBOR type 4) and Maps (CBOR type 5).
- */
-class CompoundItem : public Item {
-  public:
-    bool operator==(const CompoundItem& other) const&;
-
-    virtual size_t size() const { return mEntries.size(); }
-
-    bool isCompound() const override { return true; }
-
-    size_t encodedSize() const override {
-        return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()),
-                               [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
-    }
-
-    using Item::encode;  // Make base versions visible.
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
-    void encode(EncodeCallback encodeCallback) const override;
-
-    virtual uint64_t addlInfo() const = 0;
-
-  protected:
-    std::vector<std::unique_ptr<Item>> mEntries;
-};
-
-/*
- * Array is a concrete Item that implements CBOR major type 4.
- *
- * Note that Arrays are not copyable.  This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally.  If you actually want to copy an Array,
- * use the clone() method.
- */
-class Array : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = ARRAY;
-
-    Array() = default;
-    Array(const Array& other) = delete;
-    Array(Array&&) = default;
-    Array& operator=(const Array&) = delete;
-    Array& operator=(Array&&) = default;
-
-    /**
-     * Construct an Array from a variable number of arguments of different types.  See
-     * details::makeItem below for details on what types may be provided.  In general, this accepts
-     * all of the types you'd expect and doest the things you'd expect (integral values are addes as
-     * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.).
-     */
-    template <typename... Args, typename Enable>
-    Array(Args&&... args);
-
-    /**
-     * Append a single element to the Array, of any compatible type.
-     */
-    template <typename T>
-    Array& add(T&& v) &;
-    template <typename T>
-    Array&& add(T&& v) &&;
-
-    const std::unique_ptr<Item>& operator[](size_t index) const { return mEntries[index]; }
-    std::unique_ptr<Item>& operator[](size_t index) { return mEntries[index]; }
-
-    MajorType type() const override { return kMajorType; }
-    const Array* asArray() const override { return this; }
-
-    virtual std::unique_ptr<Item> clone() const override;
-
-    uint64_t addlInfo() const override { return size(); }
-};
-
-/*
- * Map is a concrete Item that implements CBOR major type 5.
- *
- * Note that Maps are not copyable.  This is because copying them is expensive and making them
- * move-only ensures that they're never copied accidentally.  If you actually want to copy a
- * Map, use the clone() method.
- */
-class Map : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = MAP;
-
-    Map() = default;
-    Map(const Map& other) = delete;
-    Map(Map&&) = default;
-    Map& operator=(const Map& other) = delete;
-    Map& operator=(Map&&) = default;
-
-    /**
-     * Construct a Map from a variable number of arguments of different types.  An even number of
-     * arguments must be provided (this is verified statically). See details::makeItem below for
-     * details on what types may be provided.  In general, this accepts all of the types you'd
-     * expect and doest the things you'd expect (integral values are addes as Uint or Nint,
-     * std::string and char* are added as Tstr, bools are added as Bool, etc.).
-     */
-    template <typename... Args, typename Enable>
-    Map(Args&&... args);
-
-    /**
-     * Append a key/value pair to the Map, of any compatible types.
-     */
-    template <typename Key, typename Value>
-    Map& add(Key&& key, Value&& value) &;
-    template <typename Key, typename Value>
-    Map&& add(Key&& key, Value&& value) &&;
-
-    size_t size() const override {
-        assertInvariant();
-        return mEntries.size() / 2;
-    }
-
-    template <typename Key, typename Enable>
-    std::pair<std::unique_ptr<Item>&, bool> get(Key key);
-
-    std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> operator[](
-            size_t index) const {
-        assertInvariant();
-        return {mEntries[index * 2], mEntries[index * 2 + 1]};
-    }
-
-    std::pair<std::unique_ptr<Item>&, std::unique_ptr<Item>&> operator[](size_t index) {
-        assertInvariant();
-        return {mEntries[index * 2], mEntries[index * 2 + 1]};
-    }
-
-    MajorType type() const override { return kMajorType; }
-    const Map* asMap() const override { return this; }
-
-    virtual std::unique_ptr<Item> clone() const override;
-
-    uint64_t addlInfo() const override { return size(); }
-
-  private:
-    void assertInvariant() const;
-};
-
-class Semantic : public CompoundItem {
-  public:
-    static constexpr MajorType kMajorType = SEMANTIC;
-
-    template <typename T>
-    explicit Semantic(uint64_t value, T&& child);
-
-    Semantic(const Semantic& other) = delete;
-    Semantic(Semantic&&) = default;
-    Semantic& operator=(const Semantic& other) = delete;
-    Semantic& operator=(Semantic&&) = default;
-
-    size_t size() const override {
-        assertInvariant();
-        return 1;
-    }
-
-    size_t encodedSize() const override {
-        return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(mValue),
-                               [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
-    }
-
-    MajorType type() const override { return kMajorType; }
-    const Semantic* asSemantic() const override { return this; }
-
-    const std::unique_ptr<Item>& child() const {
-        assertInvariant();
-        return mEntries[0];
-    }
-
-    std::unique_ptr<Item>& child() {
-        assertInvariant();
-        return mEntries[0];
-    }
-
-    uint64_t value() const { return mValue; }
-
-    uint64_t addlInfo() const override { return value(); }
-
-    virtual std::unique_ptr<Item> clone() const override {
-        assertInvariant();
-        return std::make_unique<Semantic>(mValue, mEntries[0]->clone());
-    }
-
-  protected:
-    Semantic() = default;
-    Semantic(uint64_t value) : mValue(value) {}
-    uint64_t mValue;
-
-  private:
-    void assertInvariant() const;
-};
-
-/**
- * Simple is abstract Item that implements CBOR major type 7.  It is intended to be subclassed to
- * create concrete Simple types.  At present only Bool is provided.
- */
-class Simple : public Item {
-  public:
-    static constexpr MajorType kMajorType = SIMPLE;
-
-    bool operator==(const Simple& other) const&;
-
-    virtual SimpleType simpleType() const = 0;
-    MajorType type() const override { return kMajorType; }
-
-    const Simple* asSimple() const override { return this; }
-
-    virtual const Bool* asBool() const { return nullptr; };
-    virtual const Null* asNull() const { return nullptr; };
-};
-
-/**
- * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE
- * and FALSE.
- */
-class Bool : public Simple {
-  public:
-    static constexpr SimpleType kSimpleType = BOOLEAN;
-
-    explicit Bool(bool v) : mValue(v) {}
-
-    bool operator==(const Bool& other) const& { return mValue == other.mValue; }
-
-    SimpleType simpleType() const override { return kSimpleType; }
-    const Bool* asBool() const override { return this; }
-
-    size_t encodedSize() const override { return 1; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(mValue ? TRUE : FALSE, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(mValue ? TRUE : FALSE, encodeCallback);
-    }
-
-    bool value() const { return mValue; }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); }
-
-  private:
-    bool mValue;
-};
-
-/**
- * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL
- */
-class Null : public Simple {
-  public:
-    static constexpr SimpleType kSimpleType = NULL_T;
-
-    explicit Null() {}
-
-    SimpleType simpleType() const override { return kSimpleType; }
-    const Null* asNull() const override { return this; }
-
-    size_t encodedSize() const override { return 1; }
-
-    using Item::encode;
-    uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
-        return encodeHeader(NULL_V, pos, end);
-    }
-    void encode(EncodeCallback encodeCallback) const override {
-        encodeHeader(NULL_V, encodeCallback);
-    }
-
-    virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); }
-};
-
-template <typename T>
-std::unique_ptr<T> downcastItem(std::unique_ptr<Item>&& v) {
-    static_assert(std::is_base_of_v<Item, T> && !std::is_abstract_v<T>,
-                  "returned type is not an Item or is an abstract class");
-    if (v && T::kMajorType == v->type()) {
-        if constexpr (std::is_base_of_v<Simple, T>) {
-            if (T::kSimpleType != v->asSimple()->simpleType()) {
-                return nullptr;
-            }
-        }
-        return std::unique_ptr<T>(static_cast<T*>(v.release()));
-    } else {
-        return nullptr;
-    }
-}
-
-/**
- * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem.
- */
-namespace details {
-
-template <typename T, typename V, typename Enable = void>
-struct is_iterator_pair_over : public std::false_type {};
-
-template <typename I1, typename I2, typename V>
-struct is_iterator_pair_over<
-        std::pair<I1, I2>, V,
-        typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>>
-    : public std::true_type {};
-
-template <typename T, typename V, typename Enable = void>
-struct is_unique_ptr_of_subclass_of_v : public std::false_type {};
-
-template <typename T, typename P>
-struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>,
-                                      typename std::enable_if_t<std::is_base_of_v<T, P>>>
-    : public std::true_type {};
-
-/* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair
- *     of iterators (4)*/
-template <typename T, typename Enable = void>
-struct is_text_type_v : public std::false_type {};
-
-template <typename T>
-struct is_text_type_v<
-        T, typename std::enable_if_t<
-                   /* case 1 */  //
-                   std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string>
-                   /* case 2 */  //
-                   || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view>
-                   /* case 3 */                                                 //
-                   || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*>  //
-                   || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*>
-                   /* case 4 */
-                   || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {};
-
-/**
- * Construct a unique_ptr<Item> from many argument types. Accepts:
- *
- * (a) booleans;
- * (b) integers, all sizes and signs;
- * (c) text strings, as defined by is_text_type_v above;
- * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T>
- *     (d3); and
- * (e) Item subclass instances, including Array and Map.  Items may be provided by naked pointer
- *     (e1), unique_ptr (e2), reference (e3) or value (e3).  If provided by reference or value, will
- *     be moved if possible.  If provided by pointer, ownership is taken.
- * (f) null pointer;
- */
-template <typename T>
-std::unique_ptr<Item> makeItem(T v) {
-    Item* p = nullptr;
-    if constexpr (/* case a */ std::is_same_v<T, bool>) {
-        p = new Bool(v);
-    } else if constexpr (/* case b */ std::is_integral_v<T>) {  // b
-        if (v < 0) {
-            p = new Nint(v);
-        } else {
-            p = new Uint(static_cast<uint64_t>(v));
-        }
-    } else if constexpr (/* case c */  //
-                         details::is_text_type_v<T>::value) {
-        p = new Tstr(v);
-    } else if constexpr (/* case d1 */  //
-                         std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
-                                        std::vector<uint8_t>>
-                         /* case d2 */  //
-                         || details::is_iterator_pair_over<T, uint8_t>::value
-                         /* case d3 */  //
-                         || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
-                                           std::pair<uint8_t*, size_t>>) {
-        p = new Bstr(v);
-    } else if constexpr (/* case e1 */  //
-                         std::is_pointer_v<T> &&
-                         std::is_base_of_v<Item, std::remove_pointer_t<T>>) {
-        p = v;
-    } else if constexpr (/* case e2 */  //
-                         details::is_unique_ptr_of_subclass_of_v<Item, T>::value) {
-        p = v.release();
-    } else if constexpr (/* case e3 */  //
-                         std::is_base_of_v<Item, T>) {
-        p = new T(std::move(v));
-    } else if constexpr (/* case f */ std::is_null_pointer_v<T>) {
-        p = new Null();
-    } else {
-        // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one
-        // of the above ifs matches.  But static_assert(false) always triggers.
-        static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type");
-    }
-    return std::unique_ptr<Item>(p);
-}
-
-}  // namespace details
-
-template <typename... Args,
-          /* Prevent use as copy ctor */ typename = std::enable_if_t<
-                  (sizeof...(Args)) != 1 ||
-                  !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>>
-Array::Array(Args&&... args) {
-    mEntries.reserve(sizeof...(args));
-    (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename T>
-Array& Array::add(T&& v) & {
-    mEntries.push_back(details::makeItem(std::forward<T>(v)));
-    return *this;
-}
-
-template <typename T>
-Array&& Array::add(T&& v) && {
-    mEntries.push_back(details::makeItem(std::forward<T>(v)));
-    return std::move(*this);
-}
-
-template <typename... Args,
-          /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
-Map::Map(Args&&... args) {
-    static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries");
-    mEntries.reserve(sizeof...(args));
-    (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
-}
-
-template <typename Key, typename Value>
-Map& Map::add(Key&& key, Value&& value) & {
-    mEntries.push_back(details::makeItem(std::forward<Key>(key)));
-    mEntries.push_back(details::makeItem(std::forward<Value>(value)));
-    return *this;
-}
-
-template <typename Key, typename Value>
-Map&& Map::add(Key&& key, Value&& value) && {
-    this->add(std::forward<Key>(key), std::forward<Value>(value));
-    return std::move(*this);
-}
-
-template <typename Key, typename = std::enable_if_t<std::is_integral_v<Key> ||
-                                                    details::is_text_type_v<Key>::value>>
-std::pair<std::unique_ptr<Item>&, bool> Map::get(Key key) {
-    assertInvariant();
-    auto keyItem = details::makeItem(key);
-    for (size_t i = 0; i < mEntries.size(); i += 2) {
-        if (*keyItem == *mEntries[i]) {
-            return {mEntries[i + 1], true};
-        }
-    }
-    return {keyItem, false};
-}
-
-template <typename T>
-Semantic::Semantic(uint64_t value, T&& child) : mValue(value) {
-    mEntries.reserve(1);
-    mEntries.push_back(details::makeItem(std::forward<T>(child)));
-}
-
-}  // namespace cppbor
diff --git a/identity/support/include/cppbor/cppbor_parse.h b/identity/support/include/cppbor/cppbor_parse.h
deleted file mode 100644
index 66cd5a3..0000000
--- a/identity/support/include/cppbor/cppbor_parse.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include "cppbor.h"
-
-namespace cppbor {
-
-using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-                               std::string /* errMsg */>;
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, end).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-ParseResult parse(const uint8_t* begin, const uint8_t* end);
-
-/**
- * Parse the first CBOR data item (possibly compound) from the byte vector.
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const std::vector<uint8_t>& encoding) {
-    return parse(encoding.data(), encoding.data() + encoding.size());
-}
-
-/**
- * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size).
- *
- * Returns a tuple of Item pointer, buffer pointer and error message.  If parsing is successful, the
- * Item pointer is non-null, the buffer pointer points to the first byte after the
- * successfully-parsed item and the error message string is empty.  If parsing fails, the Item
- * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte
- * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is
- * too large for the remining buffer, etc.) and the string contains an error message describing the
- * problem encountered.
- */
-inline ParseResult parse(const uint8_t* begin, size_t size) {
-    return parse(begin, begin + size);
-}
-
-class ParseClient;
-
-/**
- * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient);
-
-/**
- * Parse the CBOR data in the vector in streaming fashion, calling methods on the
- * provided ParseClient when elements are found.
- */
-inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) {
-    return parse(encoding.data(), encoding.data() + encoding.size(), parseClient);
-}
-
-/**
- * A pure interface that callers of the streaming parse functions must implement.
- */
-class ParseClient {
-  public:
-    virtual ~ParseClient() {}
-
-    /**
-     * Called when an item is found.  The Item pointer points to the found item; use type() and
-     * the appropriate as*() method to examine the value.  hdrBegin points to the first byte of the
-     * header, valueBegin points to the first byte of the value and end points one past the end of
-     * the item.  In the case of header-only items, such as integers, and compound items (ARRAY,
-     * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to
-     * the byte past the header.
-     *
-     * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content.  For
-     * Map and Array items, the size() method will return a correct value, but the index operators
-     * are unsafe, and the object cannot be safely compared with another Array/Map.
-     *
-     * The method returns a ParseClient*.  In most cases "return this;" will be the right answer,
-     * but a different ParseClient may be returned, which the parser will begin using. If the method
-     * returns nullptr, parsing will be aborted immediately.
-     */
-    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                              const uint8_t* valueBegin, const uint8_t* end) = 0;
-
-    /**
-     * Called when the end of a compound item (MAP or ARRAY) is found.  The item argument will be
-     * the same one passed to the item() call -- and may be empty if item() moved its value out.
-     * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the
-     * first contained value, and one past the end of the last contained value, respectively.
-     *
-     * Note that the Item will have no content.
-     *
-     * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the
-     * parsing by returning nullptr;
-     */
-    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                 const uint8_t* valueBegin, const uint8_t* end) = 0;
-
-    /**
-     * Called when parsing encounters an error.  position is set to the first unparsed byte (one
-     * past the last successfully-parsed byte) and errorMessage contains an message explaining what
-     * sort of error occurred.
-     */
-    virtual void error(const uint8_t* position, const std::string& errorMessage) = 0;
-};
-
-}  // namespace cppbor
diff --git a/identity/support/src/cppbor.cpp b/identity/support/src/cppbor.cpp
deleted file mode 100644
index d289985..0000000
--- a/identity/support/src/cppbor.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * 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.
- */
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
-Iterator writeBigEndian(T value, Iterator pos) {
-    for (unsigned i = 0; i < sizeof(value); ++i) {
-        *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
-        value = static_cast<T>(value << 8);
-    }
-    return pos;
-}
-
-template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
-void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
-    for (unsigned i = 0; i < sizeof(value); ++i) {
-        cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
-        value = static_cast<T>(value << 8);
-    }
-}
-
-}  // namespace
-
-size_t headerSize(uint64_t addlInfo) {
-    if (addlInfo < ONE_BYTE_LENGTH) return 1;
-    if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
-    if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
-    if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
-    return 9;
-}
-
-uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
-    size_t sz = headerSize(addlInfo);
-    if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
-    switch (sz) {
-        case 1:
-            *pos++ = type | static_cast<uint8_t>(addlInfo);
-            return pos;
-        case 2:
-            *pos++ = type | ONE_BYTE_LENGTH;
-            *pos++ = static_cast<uint8_t>(addlInfo);
-            return pos;
-        case 3:
-            *pos++ = type | TWO_BYTE_LENGTH;
-            return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
-        case 5:
-            *pos++ = type | FOUR_BYTE_LENGTH;
-            return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
-        case 9:
-            *pos++ = type | EIGHT_BYTE_LENGTH;
-            return writeBigEndian(addlInfo, pos);
-        default:
-            CHECK(false);  // Impossible to get here.
-            return nullptr;
-    }
-}
-
-void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
-    size_t sz = headerSize(addlInfo);
-    switch (sz) {
-        case 1:
-            encodeCallback(type | static_cast<uint8_t>(addlInfo));
-            break;
-        case 2:
-            encodeCallback(type | ONE_BYTE_LENGTH);
-            encodeCallback(static_cast<uint8_t>(addlInfo));
-            break;
-        case 3:
-            encodeCallback(type | TWO_BYTE_LENGTH);
-            writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
-            break;
-        case 5:
-            encodeCallback(type | FOUR_BYTE_LENGTH);
-            writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
-            break;
-        case 9:
-            encodeCallback(type | EIGHT_BYTE_LENGTH);
-            writeBigEndian(addlInfo, encodeCallback);
-            break;
-        default:
-            CHECK(false);  // Impossible to get here.
-    }
-}
-
-bool Item::operator==(const Item& other) const& {
-    if (type() != other.type()) return false;
-    switch (type()) {
-        case UINT:
-            return *asUint() == *(other.asUint());
-        case NINT:
-            return *asNint() == *(other.asNint());
-        case BSTR:
-            return *asBstr() == *(other.asBstr());
-        case TSTR:
-            return *asTstr() == *(other.asTstr());
-        case ARRAY:
-            return *asArray() == *(other.asArray());
-        case MAP:
-            return *asMap() == *(other.asMap());
-        case SIMPLE:
-            return *asSimple() == *(other.asSimple());
-        case SEMANTIC:
-            return *asSemantic() == *(other.asSemantic());
-        default:
-            CHECK(false);  // Impossible to get here.
-            return false;
-    }
-}
-
-Nint::Nint(int64_t v) : mValue(v) {
-    CHECK(v < 0) << "Only negative values allowed";
-}
-
-bool Simple::operator==(const Simple& other) const& {
-    if (simpleType() != other.simpleType()) return false;
-
-    switch (simpleType()) {
-        case BOOLEAN:
-            return *asBool() == *(other.asBool());
-        case NULL_T:
-            return true;
-        default:
-            CHECK(false);  // Impossible to get here.
-            return false;
-    }
-}
-
-uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(mValue.size(), pos, end);
-    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
-    return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Bstr::encodeValue(EncodeCallback encodeCallback) const {
-    for (auto c : mValue) {
-        encodeCallback(c);
-    }
-}
-
-uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(mValue.size(), pos, end);
-    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
-    return std::copy(mValue.begin(), mValue.end(), pos);
-}
-
-void Tstr::encodeValue(EncodeCallback encodeCallback) const {
-    for (auto c : mValue) {
-        encodeCallback(static_cast<uint8_t>(c));
-    }
-}
-
-bool CompoundItem::operator==(const CompoundItem& other) const& {
-    return type() == other.type()             //
-           && addlInfo() == other.addlInfo()  //
-           // Can't use vector::operator== because the contents are pointers.  std::equal lets us
-           // provide a predicate that does the dereferencing.
-           && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
-                         [](auto& a, auto& b) -> bool { return *a == *b; });
-}
-
-uint8_t* CompoundItem::encode(uint8_t* pos, const uint8_t* end) const {
-    pos = encodeHeader(addlInfo(), pos, end);
-    if (!pos) return nullptr;
-    for (auto& entry : mEntries) {
-        pos = entry->encode(pos, end);
-        if (!pos) return nullptr;
-    }
-    return pos;
-}
-
-void CompoundItem::encode(EncodeCallback encodeCallback) const {
-    encodeHeader(addlInfo(), encodeCallback);
-    for (auto& entry : mEntries) {
-        entry->encode(encodeCallback);
-    }
-}
-
-void Map::assertInvariant() const {
-    CHECK(mEntries.size() % 2 == 0);
-}
-
-std::unique_ptr<Item> Map::clone() const {
-    assertInvariant();
-    auto res = std::make_unique<Map>();
-    for (size_t i = 0; i < mEntries.size(); i += 2) {
-        res->add(mEntries[i]->clone(), mEntries[i + 1]->clone());
-    }
-    return res;
-}
-
-std::unique_ptr<Item> Array::clone() const {
-    auto res = std::make_unique<Array>();
-    for (size_t i = 0; i < mEntries.size(); i++) {
-        res->add(mEntries[i]->clone());
-    }
-    return res;
-}
-
-void Semantic::assertInvariant() const {
-    CHECK(mEntries.size() == 1);
-}
-
-}  // namespace cppbor
diff --git a/identity/support/src/cppbor_parse.cpp b/identity/support/src/cppbor_parse.cpp
deleted file mode 100644
index c9ebb8a..0000000
--- a/identity/support/src/cppbor_parse.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * 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.
- */
-
-#include "cppbor_parse.h"
-
-#include <sstream>
-#include <stack>
-
-#define LOG_TAG "CppBor"
-#include <android-base/logging.h>
-
-namespace cppbor {
-
-namespace {
-
-std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
-                                     const std::string& type) {
-    std::stringstream errStream;
-    errStream << "Need " << bytesNeeded << " byte(s) for " << type << ", have " << bytesAvail
-              << ".";
-    return errStream.str();
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
-                                                       ParseClient* parseClient) {
-    if (pos + sizeof(T) > end) {
-        parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
-        return {false, 0, pos};
-    }
-
-    const uint8_t* intEnd = pos + sizeof(T);
-    T result = 0;
-    do {
-        result = static_cast<T>((result << 8) | *pos++);
-    } while (pos < intEnd);
-    return {true, result, pos};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
-                                                          ParseClient* parseClient);
-
-std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Uint>(value);
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    if (value > std::numeric_limits<int64_t>::max()) {
-        parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
-        return {hdrBegin, nullptr /* end parsing */};
-    }
-    std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<uint64_t>(value));
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
-                                                    const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
-                                                    ParseClient* parseClient) {
-    std::unique_ptr<Item> item = std::make_unique<Null>();
-    return {hdrEnd,
-            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
-}
-
-template <typename T>
-std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
-                                                      const uint8_t* valueBegin, const uint8_t* end,
-                                                      const std::string& errLabel,
-                                                      ParseClient* parseClient) {
-    if (end - valueBegin < static_cast<ssize_t>(length)) {
-        parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
-        return {hdrBegin, nullptr /* end parsing */};
-    }
-
-    std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
-    return {valueBegin + length,
-            parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
-}
-
-class IncompleteItem {
-  public:
-    virtual ~IncompleteItem() {}
-    virtual void add(std::unique_ptr<Item> item) = 0;
-};
-
-class IncompleteArray : public Array, public IncompleteItem {
-  public:
-    IncompleteArray(size_t size) : mSize(size) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return mSize; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(mSize);
-        mEntries.push_back(std::move(item));
-    }
-
-  private:
-    size_t mSize;
-};
-
-class IncompleteMap : public Map, public IncompleteItem {
-  public:
-    IncompleteMap(size_t size) : mSize(size) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return mSize; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(mSize * 2);
-        mEntries.push_back(std::move(item));
-    }
-
-  private:
-    size_t mSize;
-};
-
-class IncompleteSemantic : public Semantic, public IncompleteItem {
-  public:
-    IncompleteSemantic(uint64_t value) : Semantic(value) {}
-
-    // We return the "complete" size, rather than the actual size.
-    size_t size() const override { return 1; }
-
-    void add(std::unique_ptr<Item> item) override {
-        mEntries.reserve(1);
-        mEntries.push_back(std::move(item));
-    }
-};
-
-std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
-                                                       const uint8_t* pos, const uint8_t* end,
-                                                       const std::string& typeName,
-                                                       ParseClient* parseClient) {
-    while (entryCount > 0) {
-        --entryCount;
-        if (pos == end) {
-            parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
-            return {hdrBegin, nullptr /* end parsing */};
-        }
-        std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
-        if (!parseClient) return {hdrBegin, nullptr};
-    }
-    return {pos, parseClient};
-}
-
-std::tuple<const uint8_t*, ParseClient*> handleCompound(
-        std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
-        const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
-        ParseClient* parseClient) {
-    parseClient =
-            parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
-    if (!parseClient) return {hdrBegin, nullptr};
-
-    const uint8_t* pos;
-    std::tie(pos, parseClient) =
-            handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
-    if (!parseClient) return {hdrBegin, nullptr};
-
-    return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
-}
-
-std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
-                                                          ParseClient* parseClient) {
-    const uint8_t* pos = begin;
-
-    MajorType type = static_cast<MajorType>(*pos & 0xE0);
-    uint8_t tagInt = *pos & 0x1F;
-    ++pos;
-
-    bool success = true;
-    uint64_t addlData;
-    if (tagInt < ONE_BYTE_LENGTH || tagInt > EIGHT_BYTE_LENGTH) {
-        addlData = tagInt;
-    } else {
-        switch (tagInt) {
-            case ONE_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
-                break;
-
-            case TWO_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
-                break;
-
-            case FOUR_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
-                break;
-
-            case EIGHT_BYTE_LENGTH:
-                std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
-                break;
-
-            default:
-                CHECK(false);  //  It's impossible to get here
-                break;
-        }
-    }
-
-    if (!success) return {begin, nullptr};
-
-    switch (type) {
-        case UINT:
-            return handleUint(addlData, begin, pos, parseClient);
-
-        case NINT:
-            return handleNint(addlData, begin, pos, parseClient);
-
-        case BSTR:
-            return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
-
-        case TSTR:
-            return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
-
-        case ARRAY:
-            return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
-                                  end, "array", parseClient);
-
-        case MAP:
-            return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
-                                  pos, end, "map", parseClient);
-
-        case SEMANTIC:
-            return handleCompound(std::make_unique<IncompleteSemantic>(addlData), 1, begin, pos,
-                                  end, "semantic", parseClient);
-
-        case SIMPLE:
-            switch (addlData) {
-                case TRUE:
-                case FALSE:
-                    return handleBool(addlData, begin, pos, parseClient);
-                case NULL_V:
-                    return handleNull(begin, pos, parseClient);
-            }
-    }
-    CHECK(false);  // Impossible to get here.
-    return {};
-}
-
-class FullParseClient : public ParseClient {
-  public:
-    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
-                              const uint8_t* end) override {
-        if (mParentStack.empty() && !item->isCompound()) {
-            // This is the first and only item.
-            mTheItem = std::move(item);
-            mPosition = end;
-            return nullptr;  //  We're done.
-        }
-
-        if (item->isCompound()) {
-            // Starting a new compound data item, i.e. a new parent.  Save it on the parent stack.
-            // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
-            // existence until the corresponding itemEnd() call.
-            assert(dynamic_cast<CompoundItem*>(item.get()));
-            mParentStack.push(static_cast<CompoundItem*>(item.get()));
-            return this;
-        } else {
-            appendToLastParent(std::move(item));
-            return this;
-        }
-    }
-
-    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
-                                 const uint8_t* end) override {
-        CHECK(item->isCompound() && item.get() == mParentStack.top());
-        mParentStack.pop();
-
-        if (mParentStack.empty()) {
-            mTheItem = std::move(item);
-            mPosition = end;
-            return nullptr;  // We're done
-        } else {
-            appendToLastParent(std::move(item));
-            return this;
-        }
-    }
-
-    virtual void error(const uint8_t* position, const std::string& errorMessage) override {
-        mPosition = position;
-        mErrorMessage = errorMessage;
-    }
-
-    std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-               std::string /* errMsg */>
-    parseResult() {
-        std::unique_ptr<Item> p = std::move(mTheItem);
-        return {std::move(p), mPosition, std::move(mErrorMessage)};
-    }
-
-  private:
-    void appendToLastParent(std::unique_ptr<Item> item) {
-        auto parent = mParentStack.top();
-        assert(dynamic_cast<IncompleteItem*>(parent));
-        if (parent->type() == ARRAY) {
-            static_cast<IncompleteArray*>(parent)->add(std::move(item));
-        } else if (parent->type() == MAP) {
-            static_cast<IncompleteMap*>(parent)->add(std::move(item));
-        } else if (parent->type() == SEMANTIC) {
-            static_cast<IncompleteSemantic*>(parent)->add(std::move(item));
-        } else {
-            CHECK(false);  // Impossible to get here.
-        }
-    }
-
-    std::unique_ptr<Item> mTheItem;
-    std::stack<CompoundItem*> mParentStack;
-    const uint8_t* mPosition = nullptr;
-    std::string mErrorMessage;
-};
-
-}  // anonymous namespace
-
-void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
-    parseRecursively(begin, end, parseClient);
-}
-
-std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
-           std::string /* errMsg */>
-parse(const uint8_t* begin, const uint8_t* end) {
-    FullParseClient parseClient;
-    parse(begin, end, &parseClient);
-    return parseClient.parseResult();
-}
-
-}  // namespace cppbor
diff --git a/identity/support/tests/cppbor_test.cpp b/identity/support/tests/cppbor_test.cpp
deleted file mode 100644
index 3eb5598..0000000
--- a/identity/support/tests/cppbor_test.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright (c) 2019, The Android Open Source Project
- *
- * 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.
- */
-
-#include <iomanip>
-#include <sstream>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "cppbor.h"
-#include "cppbor_parse.h"
-
-using namespace cppbor;
-using namespace std;
-
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::ByRef;
-using ::testing::InSequence;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::Truly;
-using ::testing::Unused;
-
-string hexDump(const string& str) {
-    stringstream s;
-    for (auto c : str) {
-        s << setfill('0') << setw(2) << hex << (static_cast<unsigned>(c) & 0xff);
-    }
-    return s.str();
-}
-
-TEST(SimpleValueTest, UnsignedValueSizes) {
-    // Check that unsigned integers encode to correct lengths, and that encodedSize() is correct.
-    vector<pair<uint64_t /* value */, size_t /* expected encoded size */>> testCases{
-            {0, 1},
-            {1, 1},
-            {23, 1},
-            {24, 2},
-            {255, 2},
-            {256, 3},
-            {65535, 3},
-            {65536, 5},
-            {4294967295, 5},
-            {4294967296, 9},
-            {std::numeric_limits<uint64_t>::max(), 9},
-    };
-    for (auto& testCase : testCases) {
-        Uint val(testCase.first);
-        EXPECT_EQ(testCase.second, val.encodedSize()) << "Wrong size for value " << testCase.first;
-        EXPECT_EQ(val.encodedSize(), val.toString().size())
-                << "encodedSize and encoding disagree for value " << testCase.first;
-    }
-}
-
-TEST(SimpleValueTest, UnsignedValueEncodings) {
-    EXPECT_EQ("\x00"s, Uint(0u).toString());
-    EXPECT_EQ("\x01"s, Uint(1u).toString());
-    EXPECT_EQ("\x0a"s, Uint(10u).toString());
-    EXPECT_EQ("\x17"s, Uint(23u).toString());
-    EXPECT_EQ("\x18\x18"s, Uint(24u).toString());
-    EXPECT_EQ("\x18\x19"s, Uint(25u).toString());
-    EXPECT_EQ("\x18\x64"s, Uint(100u).toString());
-    EXPECT_EQ("\x19\x03\xe8"s, Uint(1000u).toString());
-    EXPECT_EQ("\x1a\x00\x0f\x42\x40"s, Uint(1000000u).toString());
-    EXPECT_EQ("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"s, Uint(1000000000000u).toString());
-    EXPECT_EQ("\x1B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
-              Uint(std::numeric_limits<int64_t>::max()).toString());
-}
-
-TEST(SimpleValueTest, NegativeValueEncodings) {
-    EXPECT_EQ("\x20"s, Nint(-1).toString());
-    EXPECT_EQ("\x28"s, Nint(-9).toString());
-    EXPECT_EQ("\x29"s, Nint(-10).toString());
-    EXPECT_EQ("\x36"s, Nint(-23).toString());
-    EXPECT_EQ("\x37"s, Nint(-24).toString());
-    EXPECT_EQ("\x38\x18"s, Nint(-25).toString());
-    EXPECT_EQ("\x38\x62"s, Nint(-99).toString());
-    EXPECT_EQ("\x38\x63"s, Nint(-100).toString());
-    EXPECT_EQ("\x39\x03\xe6"s, Nint(-999).toString());
-    EXPECT_EQ("\x39\x03\xe7"s, Nint(-1000).toString());
-    EXPECT_EQ("\x3a\x00\x0f\x42\x3F"s, Nint(-1000000).toString());
-    EXPECT_EQ("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"s, Nint(-1000000000000).toString());
-    EXPECT_EQ("\x3B\x7f\xff\xff\xff\xff\xff\xff\xff"s,
-              Nint(std::numeric_limits<int64_t>::min()).toString());
-}
-
-TEST(SimpleValueDeathTest, NegativeValueEncodings) {
-    EXPECT_DEATH(Nint(0), "");
-    EXPECT_DEATH(Nint(1), "");
-}
-
-TEST(SimpleValueTest, BooleanEncodings) {
-    EXPECT_EQ("\xf4"s, Bool(false).toString());
-    EXPECT_EQ("\xf5"s, Bool(true).toString());
-}
-
-TEST(SimpleValueTest, ByteStringEncodings) {
-    EXPECT_EQ("\x40", Bstr("").toString());
-    EXPECT_EQ("\x41\x61", Bstr("a").toString());
-    EXPECT_EQ("\x41\x41", Bstr("A").toString());
-    EXPECT_EQ("\x44\x49\x45\x54\x46", Bstr("IETF").toString());
-    EXPECT_EQ("\x42\x22\x5c", Bstr("\"\\").toString());
-    EXPECT_EQ("\x42\xc3\xbc", Bstr("\xc3\xbc").toString());
-    EXPECT_EQ("\x43\xe6\xb0\xb4", Bstr("\xe6\xb0\xb4").toString());
-    EXPECT_EQ("\x44\xf0\x90\x85\x91", Bstr("\xf0\x90\x85\x91").toString());
-    EXPECT_EQ("\x44\x01\x02\x03\x04", Bstr("\x01\x02\x03\x04").toString());
-    EXPECT_EQ("\x44\x40\x40\x40\x40", Bstr("@@@@").toString());
-}
-
-TEST(SimpleValueTest, TextStringEncodings) {
-    EXPECT_EQ("\x60"s, Tstr("").toString());
-    EXPECT_EQ("\x61\x61"s, Tstr("a").toString());
-    EXPECT_EQ("\x61\x41"s, Tstr("A").toString());
-    EXPECT_EQ("\x64\x49\x45\x54\x46"s, Tstr("IETF").toString());
-    EXPECT_EQ("\x62\x22\x5c"s, Tstr("\"\\").toString());
-    EXPECT_EQ("\x62\xc3\xbc"s, Tstr("\xc3\xbc").toString());
-    EXPECT_EQ("\x63\xe6\xb0\xb4"s, Tstr("\xe6\xb0\xb4").toString());
-    EXPECT_EQ("\x64\xf0\x90\x85\x91"s, Tstr("\xf0\x90\x85\x91").toString());
-    EXPECT_EQ("\x64\x01\x02\x03\x04"s, Tstr("\x01\x02\x03\x04").toString());
-}
-
-TEST(IsIteratorPairOverTest, All) {
-    EXPECT_TRUE((
-            details::is_iterator_pair_over<pair<string::iterator, string::iterator>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<string::const_iterator, string::iterator>,
-                                                char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<string::iterator, string::const_iterator>,
-                                                char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, char*>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<const char*, char*>, char>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<char*, const char*>, char>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<string::iterator, string::iterator>,
-                                                 uint8_t>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<char*, char*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::const_iterator, vector<uint8_t>::iterator>,
-                 uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<
-                 pair<vector<uint8_t>::iterator, vector<uint8_t>::const_iterator>,
-                 uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, uint8_t*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<const uint8_t*, uint8_t*>, uint8_t>::value));
-    EXPECT_TRUE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, uint8_t>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<
-                  pair<vector<uint8_t>::iterator, vector<uint8_t>::iterator>, char>::value));
-    EXPECT_FALSE((details::is_iterator_pair_over<pair<uint8_t*, const uint8_t*>, char>::value));
-}
-
-TEST(MakeEntryTest, Boolean) {
-    EXPECT_EQ("\xf4"s, details::makeItem(false)->toString());
-}
-
-TEST(MakeEntryTest, Integers) {
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint8_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint16_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint32_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<uint64_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int8_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int16_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int32_t>(0))->toString());
-    EXPECT_EQ("\x00"s, details::makeItem(static_cast<int64_t>(0))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int8_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int16_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int32_t>(-1))->toString());
-    EXPECT_EQ("\x20"s, details::makeItem(static_cast<int64_t>(-1))->toString());
-
-    EXPECT_EQ("\x1b\xff\xff\xff\xff\xff\xff\xff\xff"s,
-              details::makeItem(static_cast<uint64_t>(std::numeric_limits<uint64_t>::max()))
-                      ->toString());
-}
-
-TEST(MakeEntryTest, StdStrings) {
-    string s1("hello");
-    const string s2("hello");
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());  // copy of string
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
-              details::makeItem(s2)->toString());  // copy of const string
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s,
-              details::makeItem(std::move(s1))->toString());  // move string
-    EXPECT_EQ(0U, s1.size());                                 // Prove string was moved, not copied.
-}
-
-TEST(MakeEntryTest, StdStringViews) {
-    string_view s1("hello");
-    const string_view s2("hello");
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-}
-
-TEST(MakeEntryTest, CStrings) {
-    char s1[] = "hello";
-    const char s2[] = "hello";
-    const char* s3 = "hello";
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s2)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(s3)->toString());
-}
-
-TEST(MakeEntryTest, StringIteratorPairs) {
-    // Use iterators from string to prove that "real" iterators work
-    string s1 = "hello"s;
-    pair<string::iterator, string::iterator> p1 = make_pair(s1.begin(), s1.end());
-
-    const pair<string::iterator, string::iterator> p2 = p1;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p2)->toString());
-
-    // Use char*s  as iterators
-    const char* s2 = "hello";
-    pair p3 = make_pair(s2, s2 + 5);
-    const pair p4 = p3;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p3)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(p4)->toString());
-}
-
-TEST(MakeEntryTest, ByteStrings) {
-    vector<uint8_t> v1 = {0x00, 0x01, 0x02};
-    const vector<uint8_t> v2 = {0x00, 0x01, 0x02};
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v1)->toString());  // copy of vector
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(v2)->toString());  // copy of const vector
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(std::move(v1))->toString());  // move vector
-    EXPECT_EQ(0U, v1.size());  // Prove vector was moved, not copied.
-}
-
-TEST(MakeEntryTest, ByteStringIteratorPairs) {
-    using vec = vector<uint8_t>;
-    using iter = vec::iterator;
-    vec v1 = {0x00, 0x01, 0x02};
-    pair<iter, iter> p1 = make_pair(v1.begin(), v1.end());
-    const pair<iter, iter> p2 = make_pair(v1.begin(), v1.end());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p2)->toString());
-
-    // Use uint8_t*s as iterators
-    uint8_t v2[] = {0x00, 0x01, 0x02};
-    uint8_t* v3 = v2;
-    pair<uint8_t*, uint8_t*> p3 = make_pair(v2, v2 + 3);
-    const pair<uint8_t*, uint8_t*> p4 = make_pair(v2, v2 + 3);
-    pair<uint8_t*, uint8_t*> p5 = make_pair(v3, v3 + 3);
-    const pair<uint8_t*, uint8_t*> p6 = make_pair(v3, v3 + 3);
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p3)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p4)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p5)->toString());
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(p6)->toString());
-}
-
-TEST(MakeEntryTest, ByteStringBuffers) {
-    uint8_t v1[] = {0x00, 0x01, 0x02};
-    EXPECT_EQ("\x43\x00\x01\x02"s, details::makeItem(make_pair(v1, 3))->toString());
-}
-
-TEST(MakeEntryTest, ItemPointer) {
-    Uint* p1 = new Uint(0);
-    EXPECT_EQ("\x00"s, details::makeItem(p1)->toString());
-    EXPECT_EQ("\x60"s, details::makeItem(new Tstr(string()))->toString());
-}
-
-TEST(MakeEntryTest, ItemReference) {
-    Tstr str("hello"s);
-    Tstr& strRef = str;
-    const Tstr& strConstRef = str;
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(str)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strRef)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(strConstRef)->toString());
-    EXPECT_EQ("\x65\x68\x65\x6c\x6c\x6f"s, details::makeItem(std::move(str))->toString());
-    EXPECT_EQ("\x60"s, details::makeItem(str)->toString());  // Prove that it moved
-
-    EXPECT_EQ("\x00"s, details::makeItem(Uint(0))->toString());
-
-    EXPECT_EQ("\x43\x00\x01\x02"s,
-              details::makeItem(Bstr(vector<uint8_t>{0x00, 0x01, 0x02}))->toString());
-
-    EXPECT_EQ("\x80"s, details::makeItem(Array())->toString());
-    EXPECT_EQ("\xa0"s, details::makeItem(Map())->toString());
-}
-
-TEST(CompoundValueTest, ArrayOfInts) {
-    EXPECT_EQ("\x80"s, Array().toString());
-    Array(Uint(0)).toString();
-
-    EXPECT_EQ("\x81\x00"s, Array(Uint(0U)).toString());
-    EXPECT_EQ("\x82\x00\x01"s, Array(Uint(0), Uint(1)).toString());
-    EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(Uint(0), Uint(1), Nint(-99)).toString());
-
-    EXPECT_EQ("\x81\x00"s, Array(0).toString());
-    EXPECT_EQ("\x82\x00\x01"s, Array(0, 1).toString());
-    EXPECT_EQ("\x83\x00\x01\x38\x62"s, Array(0, 1, -99).toString());
-}
-
-TEST(CompoundValueTest, MapOfInts) {
-    EXPECT_EQ("\xA0"s, Map().toString());
-    EXPECT_EQ("\xA1\x00\x01"s, Map(Uint(0), Uint(1)).toString());
-    // Maps with an odd number of arguments will fail to compile.  Uncomment the next lines to test.
-    // EXPECT_EQ("\xA1\x00"s, Map(Int(0)).toString());
-    // EXPECT_EQ("\xA1\x00\x01\x02"s, Map(Int(0), Int(1), Int(2)).toString());
-}
-
-TEST(CompoundValueTest, MixedArray) {
-    vector<uint8_t> vec = {3, 2, 1};
-    EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Array(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
-    EXPECT_EQ("\x84\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Array(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, MixedMap) {
-    vector<uint8_t> vec = {3, 2, 1};
-    EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Map(Uint(1), Nint(-1), Bstr(vec), Tstr("hello")).toString());
-
-    EXPECT_EQ("\xA2\x01\x20\x43\x03\x02\x01\x65\x68\x65\x6C\x6C\x6F"s,
-              Map(1, -1, vec, "hello").toString());
-}
-
-TEST(CompoundValueTest, NestedStructures) {
-    vector<uint8_t> vec = {3, 2, 1};
-
-    string expectedEncoding =
-            "\xA2\x66\x4F\x75\x74\x65\x72\x31\x82\xA2\x66\x49\x6E\x6E\x65\x72\x31\x18\x63\x66\x49"
-            "\x6E"
-            "\x6E\x65\x72\x32\x43\x03\x02\x01\x63\x66\x6F\x6F\x66\x4F\x75\x74\x65\x72\x32\x0A"s;
-
-    // Do it with explicitly-created Items
-    EXPECT_EQ(expectedEncoding,
-              Map(Tstr("Outer1"),
-                  Array(  //
-                          Map(Tstr("Inner1"), Uint(99), Tstr("Inner2"), Bstr(vec)), Tstr("foo")),
-                  Tstr("Outer2"),  //
-                  Uint(10))
-                      .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Now just use convertible types
-    EXPECT_EQ(expectedEncoding, Map("Outer1",
-                                    Array(Map("Inner1", 99,  //
-                                              "Inner2", vec),
-                                          "foo"),
-                                    "Outer2", 10)
-                                        .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Finally, do it with the .add() method.  This is slightly less efficient, but has the
-    // advantage you can build a structure up incrementally, or somewhat fluently if you like.
-    // First, fluently.
-    EXPECT_EQ(expectedEncoding, Map().add("Outer1", Array().add(Map()  //
-                                                                        .add("Inner1", 99)
-                                                                        .add("Inner2", vec))
-                                                            .add("foo"))
-                                        .add("Outer2", 10)
-                                        .toString());
-    EXPECT_EQ(3U, vec.size());
-
-    // Next, more incrementally
-    Array arr;
-    arr.add(Map()  //
-                    .add("Inner1", 99)
-                    .add("Inner2", vec))
-            .add("foo");
-    EXPECT_EQ(3U, vec.size());
-
-    Map m;
-    m.add("Outer1", std::move(arr));  // Moving is necessary; Map and Array cannot be copied.
-    m.add("Outer2", 10);
-    auto s = m.toString();
-    EXPECT_EQ(expectedEncoding, s);
-}
-
-TEST(EncodingMethodsTest, AllVariants) {
-    Map map;
-    map.add("key1", Array().add(Map()  //
-                                        .add("key_a", 9999999)
-                                        .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03})
-                                        .add("key_c", std::numeric_limits<uint64_t>::max())
-                                        .add("key_d", std::numeric_limits<int16_t>::min()))
-                            .add("foo"))
-            .add("key2", true);
-
-    std::vector<uint8_t> buf;
-    buf.resize(map.encodedSize());
-
-    EXPECT_EQ(buf.data() + buf.size(), map.encode(buf.data(), buf.data() + buf.size()));
-
-    EXPECT_EQ(buf, map.encode());
-
-    std::vector<uint8_t> buf2;
-    map.encode(std::back_inserter(buf2));
-    EXPECT_EQ(buf, buf2);
-
-    auto iter = buf.begin();
-    map.encode([&](uint8_t c) { EXPECT_EQ(c, *iter++); });
-}
-
-TEST(EncodingMethodsTest, UintWithTooShortBuf) {
-    Uint val(100000);
-    vector<uint8_t> buf(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, TstrWithTooShortBuf) {
-    Tstr val("01234567890123456789012345"s);
-    vector<uint8_t> buf(1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
-    buf.resize(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, BstrWithTooShortBuf) {
-    Bstr val("01234567890123456789012345"s);
-    vector<uint8_t> buf(1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-
-    buf.resize(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, ArrayWithTooShortBuf) {
-    Array val("a", 5, -100);
-
-    std::vector<uint8_t> buf(val.encodedSize() - 1);
-    EXPECT_EQ(nullptr, val.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EncodingMethodsTest, MapWithTooShortBuf) {
-    Map map;
-    map.add("key1", Array().add(Map()  //
-                                        .add("key_a", 99)
-                                        .add("key_b", std::vector<uint8_t>{0x01, 0x02, 0x03}))
-                            .add("foo"))
-            .add("key2", true);
-
-    std::vector<uint8_t> buf(map.encodedSize() - 1);
-    EXPECT_EQ(nullptr, map.encode(buf.data(), buf.data() + buf.size()));
-}
-
-TEST(EqualityTest, Uint) {
-    Uint val(99);
-    EXPECT_EQ(val, Uint(99));
-
-    EXPECT_NE(val, Uint(98));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Nint) {
-    Nint val(-1);
-    EXPECT_EQ(val, Nint(-1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Tstr) {
-    Tstr val("99");
-    EXPECT_EQ(val, Tstr("99"));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("98"));
-    EXPECT_NE(val, Bstr("99"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bstr) {
-    Bstr val("99");
-    EXPECT_EQ(val, Bstr("99"));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(false));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Bool) {
-    Bool val(false);
-    EXPECT_EQ(val, Bool(false));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Array) {
-    Array val(99, 1);
-    EXPECT_EQ(val, Array(99, 1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 2));
-    EXPECT_NE(val, Array(98, 1));
-    EXPECT_NE(val, Array(99, 1, 2));
-    EXPECT_NE(val, Map(99, 1));
-}
-
-TEST(EqualityTest, Map) {
-    Map val(99, 1);
-    EXPECT_EQ(val, Map(99, 1));
-
-    EXPECT_NE(val, Uint(99));
-    EXPECT_NE(val, Nint(-1));
-    EXPECT_NE(val, Nint(-4));
-    EXPECT_NE(val, Tstr("99"));
-    EXPECT_NE(val, Bstr("98"));
-    EXPECT_NE(val, Bool(true));
-    EXPECT_NE(val, Array(99, 1));
-    EXPECT_NE(val, Map(99, 2));
-    EXPECT_NE(val, Map(99, 1, 99, 2));
-}
-
-TEST(ConvertTest, Uint) {
-    unique_ptr<Item> item = details::makeItem(10);
-
-    EXPECT_EQ(UINT, item->type());
-    EXPECT_NE(nullptr, item->asInt());
-    EXPECT_NE(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(10, item->asInt()->value());
-    EXPECT_EQ(10, item->asUint()->value());
-}
-
-TEST(ConvertTest, Nint) {
-    unique_ptr<Item> item = details::makeItem(-10);
-
-    EXPECT_EQ(NINT, item->type());
-    EXPECT_NE(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_NE(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(-10, item->asInt()->value());
-    EXPECT_EQ(-10, item->asNint()->value());
-}
-
-TEST(ConvertTest, Tstr) {
-    unique_ptr<Item> item = details::makeItem("hello");
-
-    EXPECT_EQ(TSTR, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_NE(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ("hello"s, item->asTstr()->value());
-}
-
-TEST(ConvertTest, Bstr) {
-    vector<uint8_t> vec{0x23, 0x24, 0x22};
-    unique_ptr<Item> item = details::makeItem(vec);
-
-    EXPECT_EQ(BSTR, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_NE(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(vec, item->asBstr()->value());
-}
-
-TEST(ConvertTest, Bool) {
-    unique_ptr<Item> item = details::makeItem(false);
-
-    EXPECT_EQ(SIMPLE, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_NE(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(BOOLEAN, item->asSimple()->simpleType());
-    EXPECT_NE(nullptr, item->asSimple()->asBool());
-
-    EXPECT_FALSE(item->asSimple()->asBool()->value());
-}
-
-TEST(ConvertTest, Map) {
-    unique_ptr<Item> item(new Map);
-
-    EXPECT_EQ(MAP, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_NE(nullptr, item->asMap());
-    EXPECT_EQ(nullptr, item->asArray());
-
-    EXPECT_EQ(0U, item->asMap()->size());
-}
-
-TEST(ConvertTest, Array) {
-    unique_ptr<Item> item(new Array);
-
-    EXPECT_EQ(ARRAY, item->type());
-    EXPECT_EQ(nullptr, item->asInt());
-    EXPECT_EQ(nullptr, item->asUint());
-    EXPECT_EQ(nullptr, item->asNint());
-    EXPECT_EQ(nullptr, item->asTstr());
-    EXPECT_EQ(nullptr, item->asBstr());
-    EXPECT_EQ(nullptr, item->asSimple());
-    EXPECT_EQ(nullptr, item->asMap());
-    EXPECT_NE(nullptr, item->asArray());
-
-    EXPECT_EQ(0U, item->asArray()->size());
-}
-
-class MockParseClient : public ParseClient {
-  public:
-    MOCK_METHOD4(item, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                    const uint8_t* valueBegin, const uint8_t* end));
-    MOCK_METHOD4(itemEnd, ParseClient*(std::unique_ptr<Item>& item, const uint8_t* hdrBegin,
-                                       const uint8_t* valueBegin, const uint8_t* end));
-    MOCK_METHOD2(error, void(const uint8_t* position, const std::string& errorMessage));
-};
-
-MATCHER_P(IsType, value, std::string("Type ") + (negation ? "doesn't match" : "matches")) {
-    return arg->type() == value;
-}
-
-MATCHER_P(MatchesItem, value, "") {
-    return arg && *arg == value;
-}
-
-MATCHER_P(IsArrayOfSize, value, "") {
-    return arg->type() == ARRAY && arg->asArray()->size() == value;
-}
-
-MATCHER_P(IsMapOfSize, value, "") {
-    return arg->type() == MAP && arg->asMap()->size() == value;
-}
-
-TEST(StreamParseTest, Uint) {
-    MockParseClient mpc;
-
-    Uint val(100);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Nint) {
-    MockParseClient mpc;
-
-    Nint val(-10);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bool) {
-    MockParseClient mpc;
-
-    Bool val(true);
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encEnd, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Tstr) {
-    MockParseClient mpc;
-
-    Tstr val("Hello");
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Bstr) {
-    MockParseClient mpc;
-
-    Bstr val("Hello");
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    EXPECT_CALL(mpc, item(MatchesItem(val), encBegin, encBegin + 1, encEnd)).WillOnce(Return(&mpc));
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(_, _)).Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Array) {
-    MockParseClient mpc;
-
-    Array val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
-    ASSERT_NE(val[2]->asArray(), nullptr);
-    const Array& interior = *(val[2]->asArray());
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    {
-        InSequence s;
-        const uint8_t* pos = encBegin;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(val.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0])), pos, pos + 1, pos + 6))
-                .WillOnce(Return(&mpc));
-        pos += 6;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        const uint8_t* innerArrayBegin = pos;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
-                .WillOnce(Return(&mpc));
-        pos += 8;
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
-                                 innerArrayBegin + 1, pos))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[3])), pos, pos + 9, pos + 9))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(val.size()), encBegin, encBegin + 1, encEnd))
-                .WillOnce(Return(&mpc));
-    }
-
-    EXPECT_CALL(mpc, error(_, _))  //
-            .Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Map) {
-    MockParseClient mpc;
-
-    Map val("Hello", 4, Array(-9, "Goodbye"), std::numeric_limits<uint64_t>::max());
-    ASSERT_NE(val[1].first->asArray(), nullptr);
-    const Array& interior = *(val[1].first->asArray());
-    auto encoded = val.encode();
-    uint8_t* encBegin = encoded.data();
-    uint8_t* encEnd = encoded.data() + encoded.size();
-
-    {
-        InSequence s;
-        const uint8_t* pos = encBegin;
-        EXPECT_CALL(mpc, item(_, pos, pos + 1, pos + 1)).WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].first)), pos, pos + 1, pos + 6))
-                .WillOnce(Return(&mpc));
-        pos += 6;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[0].second)), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        const uint8_t* innerArrayBegin = pos;
-        EXPECT_CALL(mpc, item(IsArrayOfSize(interior.size()), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[0])), pos, pos + 1, pos + 1))
-                .WillOnce(Return(&mpc));
-        ++pos;
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*interior[1])), pos, pos + 1, pos + 8))
-                .WillOnce(Return(&mpc));
-        pos += 8;
-        EXPECT_CALL(mpc, itemEnd(IsArrayOfSize(interior.size()), innerArrayBegin,
-                                 innerArrayBegin + 1, pos))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, item(MatchesItem(ByRef(*val[1].second)), pos, pos + 9, pos + 9))
-                .WillOnce(Return(&mpc));
-        EXPECT_CALL(mpc, itemEnd(IsMapOfSize(val.size()), encBegin, encBegin + 1, encEnd))
-                .WillOnce(Return(&mpc));
-    }
-
-    EXPECT_CALL(mpc, error(_, _))  //
-            .Times(0);
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(StreamParseTest, Semantic) {
-    MockParseClient mpc;
-
-    vector<uint8_t> encoded;
-    auto iter = back_inserter(encoded);
-    encodeHeader(SEMANTIC, 0, iter);
-    Uint(999).encode(iter);
-
-    EXPECT_CALL(mpc, item(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, itemEnd(_, _, _, _)).Times(0);
-    EXPECT_CALL(mpc, error(encoded.data(), "Semantic tags not supported"));
-
-    parse(encoded.data(), encoded.data() + encoded.size(), &mpc);
-}
-
-TEST(FullParserTest, Uint) {
-    Uint val(10);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Nint) {
-    Nint val(-10);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-
-    vector<uint8_t> minNint = {0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-    std::tie(item, pos, message) = parse(minNint);
-    EXPECT_THAT(item, NotNull());
-    EXPECT_EQ(item->asNint()->value(), std::numeric_limits<int64_t>::min());
-}
-
-TEST(FullParserTest, NintOutOfRange) {
-    vector<uint8_t> outOfRangeNint = {0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-    auto [item, pos, message] = parse(outOfRangeNint);
-    EXPECT_THAT(item, IsNull());
-    EXPECT_EQ(pos, outOfRangeNint.data());
-    EXPECT_EQ(message, "NINT values that don't fit in int64_t are not supported.");
-}
-
-TEST(FullParserTest, Tstr) {
-    Tstr val("Hello");
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Bstr) {
-    Bstr val("\x00\x01\0x02"s);
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(val));
-}
-
-TEST(FullParserTest, Array) {
-    Array val("hello", -4, 3);
-
-    auto encoded = val.encode();
-    auto [item, pos, message] = parse(encoded);
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-    EXPECT_EQ(pos, encoded.data() + encoded.size());
-    EXPECT_EQ("", message);
-
-    // We've already checked it all, but walk it just for fun.
-    ASSERT_NE(nullptr, item->asArray());
-    const Array& arr = *(item->asArray());
-    ASSERT_EQ(arr[0]->type(), TSTR);
-    EXPECT_EQ(arr[0]->asTstr()->value(), "hello");
-}
-
-TEST(FullParserTest, Map) {
-    Map val("hello", -4, 3, Bstr("hi"));
-
-    auto [item, pos, message] = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, Complex) {
-    vector<uint8_t> vec = {0x01, 0x02, 0x08, 0x03};
-    Map val("Outer1",
-            Array(Map("Inner1", 99,  //
-                      "Inner2", vec),
-                  "foo"),
-            "Outer2", 10);
-
-    std::unique_ptr<Item> item;
-    const uint8_t* pos;
-    std::string message;
-    std::tie(item, pos, message) = parse(val.encode());
-    EXPECT_THAT(item, MatchesItem(ByRef(val)));
-}
-
-TEST(FullParserTest, IncompleteUint) {
-    Uint val(1000);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Need 2 byte(s) for length field, have 1.", message);
-}
-
-TEST(FullParserTest, IncompleteString) {
-    Tstr val("hello");
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Need 5 byte(s) for text string, have 3.", message);
-}
-
-TEST(FullParserTest, ArrayWithInsufficientEntries) {
-    Array val(1, 2, 3, 4);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data(), pos);
-    EXPECT_EQ("Not enough entries for array.", message);
-}
-
-TEST(FullParserTest, ArrayWithTruncatedEntry) {
-    Array val(1, 2, 3, 400000);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 1);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data() + encoding.size() - 5, pos);
-    EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-
-TEST(FullParserTest, MapWithTruncatedEntry) {
-    Map val(1, 2, 300000, 4);
-
-    auto encoding = val.encode();
-    auto [item, pos, message] = parse(encoding.data(), encoding.size() - 2);
-    EXPECT_EQ(nullptr, item.get());
-    EXPECT_EQ(encoding.data() + 3, pos);
-    EXPECT_EQ("Need 4 byte(s) for length field, have 3.", message);
-}
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}