[BinaryFormat] Add MessagePack reader/writer
Add support for reading and writing MessagePack, a binary object serialization
format which aims to be more compact than text formats like JSON or YAML.
The specification can be found at
https://github.com/msgpack/msgpack/blob/master/spec.md
Will be used for encoding metadata in AMDGPU code objects.
Differential Revision: https://reviews.llvm.org/D44429
llvm-svn: 340457
diff --git a/llvm/unittests/BinaryFormat/CMakeLists.txt b/llvm/unittests/BinaryFormat/CMakeLists.txt
index 95c672e..c0aac4d 100644
--- a/llvm/unittests/BinaryFormat/CMakeLists.txt
+++ b/llvm/unittests/BinaryFormat/CMakeLists.txt
@@ -5,6 +5,8 @@
 add_llvm_unittest(BinaryFormatTests
   DwarfTest.cpp
   MachOTest.cpp
+  MsgPackReaderTest.cpp
+  MsgPackWriterTest.cpp
   TestFileMagic.cpp
   )
 
diff --git a/llvm/unittests/BinaryFormat/MsgPackReaderTest.cpp b/llvm/unittests/BinaryFormat/MsgPackReaderTest.cpp
new file mode 100644
index 0000000..e3c1bbb
--- /dev/null
+++ b/llvm/unittests/BinaryFormat/MsgPackReaderTest.cpp
@@ -0,0 +1,891 @@
+//===- MsgPackReaderTest.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackReader.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::msgpack;
+
+struct MsgPackReader : testing::Test {
+  std::string Buffer;
+  Object Obj;
+};
+
+TEST_F(MsgPackReader, TestReadMultiple) {
+  Buffer = "\xc0\xc2";
+  Reader MPReader(Buffer);
+  {
+    auto ContinueOrErr = MPReader.read(Obj);
+    EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+    EXPECT_TRUE(*ContinueOrErr);
+    EXPECT_EQ(Obj.Kind, Type::Nil);
+  }
+  {
+    auto ContinueOrErr = MPReader.read(Obj);
+    EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+    EXPECT_TRUE(*ContinueOrErr);
+    EXPECT_EQ(Obj.Kind, Type::Boolean);
+    EXPECT_EQ(Obj.Bool, false);
+  }
+  {
+    auto ContinueOrErr = MPReader.read(Obj);
+    EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+    EXPECT_FALSE(*ContinueOrErr);
+  }
+}
+
+TEST_F(MsgPackReader, TestReadNil) {
+  Buffer = "\xc0";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Nil);
+}
+
+TEST_F(MsgPackReader, TestReadBoolFalse) {
+  Buffer = "\xc2";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Boolean);
+  EXPECT_EQ(Obj.Bool, false);
+}
+
+TEST_F(MsgPackReader, TestReadBoolTrue) {
+  Buffer = "\xc3";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Boolean);
+  EXPECT_EQ(Obj.Bool, true);
+}
+
+TEST_F(MsgPackReader, TestReadFixNegativeInt) {
+  // Positive values will be written in a UInt form, so max FixNegativeInt is -1
+  //
+  // FixNegativeInt form bitpattern starts with 111, so min FixNegativeInt
+  // is 11100000 = -32
+  for (int8_t i = -1; i >= -32; --i) {
+    Buffer.assign(1, static_cast<char>(i));
+    Reader MPReader(Buffer);
+    auto ContinueOrErr = MPReader.read(Obj);
+    EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+    EXPECT_TRUE(*ContinueOrErr);
+    EXPECT_EQ(Obj.Kind, Type::Int);
+    EXPECT_EQ(Obj.Int, i);
+  }
+}
+
+TEST_F(MsgPackReader, TestReadInt8Max) {
+  Buffer = "\xd0\x7f";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT8_MAX);
+}
+
+TEST_F(MsgPackReader, TestReadInt8Zero) {
+  Buffer.assign("\xd0\x00", 2);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, 0);
+}
+
+TEST_F(MsgPackReader, TestReadInt8Min) {
+  Buffer = "\xd0\x80";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT8_MIN);
+}
+
+TEST_F(MsgPackReader, TestReadInt16Max) {
+  Buffer = "\xd1\x7f\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT16_MAX);
+}
+
+TEST_F(MsgPackReader, TestReadInt16Zero) {
+  Buffer.assign("\xd1\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, 0);
+}
+
+TEST_F(MsgPackReader, TestReadInt16Min) {
+  Buffer.assign("\xd1\x80\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT16_MIN);
+}
+
+TEST_F(MsgPackReader, TestReadInt32Max) {
+  Buffer = "\xd2\x7f\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT32_MAX);
+}
+
+TEST_F(MsgPackReader, TestReadInt32Zero) {
+  Buffer.assign("\xd2\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, 0);
+}
+
+TEST_F(MsgPackReader, TestReadInt32Min) {
+  Buffer.assign("\xd2\x80\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT32_MIN);
+}
+
+TEST_F(MsgPackReader, TestReadInt64Max) {
+  Buffer = "\xd3\x7f\xff\xff\xff\xff\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT64_MAX);
+}
+
+TEST_F(MsgPackReader, TestReadInt64Zero) {
+  Buffer.assign("\xd3\x00\x00\x00\x00\x00\x00\x00\x00", 9);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, 0);
+}
+
+TEST_F(MsgPackReader, TestReadInt64Min) {
+  Buffer.assign("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 9);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Int);
+  EXPECT_EQ(Obj.Int, INT64_MIN);
+}
+
+TEST_F(MsgPackReader, TestReadFixPositiveInt) {
+  // FixPositiveInt form bitpattern starts with 0, so max FixPositiveInt
+  // is 01111111 = 127
+  for (uint64_t u = 0; u <= 127; ++u) {
+    Buffer.assign(1, static_cast<char>(u));
+    Reader MPReader(Buffer);
+    auto ContinueOrErr = MPReader.read(Obj);
+    EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+    EXPECT_TRUE(*ContinueOrErr);
+    EXPECT_EQ(Obj.Kind, Type::UInt);
+    EXPECT_EQ(Obj.UInt, u);
+  }
+}
+
+TEST_F(MsgPackReader, TestReadUInt8Zero) {
+  Buffer.assign("\xcc\x00", 2);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt8One) {
+  Buffer = "\xcc\x01";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt8Max) {
+  Buffer = "\xcc\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, static_cast<uint8_t>(UINT8_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadUInt16Zero) {
+  Buffer.assign("\xcd\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt16One) {
+  Buffer.assign("\xcd\x00\x01", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt16Max) {
+  Buffer = "\xcd\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, static_cast<uint16_t>(UINT16_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadUInt32Zero) {
+  Buffer.assign("\xce\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt32One) {
+  Buffer.assign("\xce\x00\x00\x00\x01", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt32Max) {
+  Buffer = "\xce\xff\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, static_cast<uint32_t>(UINT32_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadUInt64Zero) {
+  Buffer.assign("\xcf\x00\x00\x00\x00\x00\x00\x00\x00", 9);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt64One) {
+  Buffer.assign("\xcf\x00\x00\x00\x00\x00\x00\x00\x01", 9);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadUInt64Max) {
+  Buffer = "\xcf\xff\xff\xff\xff\xff\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::UInt);
+  EXPECT_EQ(Obj.UInt, static_cast<uint64_t>(UINT64_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadFloat32) {
+  Buffer = "\xca\xee\xee\xee\xef";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Float);
+  EXPECT_EQ(Obj.Float, -3.6973142664068907e+28f);
+}
+
+TEST_F(MsgPackReader, TestReadFloat64) {
+  Buffer = "\xcb\xee\xee\xee\xee\xee\xee\xee\xef";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Float);
+  EXPECT_EQ(Obj.Float, -2.2899894549927042e+226);
+}
+
+TEST_F(MsgPackReader, TestReadFixStrZero) {
+  Buffer = "\xa0";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadFixStrOne) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xa1") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixStrMax) {
+  // FixStr format's size is a 5 bit unsigned integer, so max is 11111 = 31
+  std::string Result(31, 'a');
+  Buffer = std::string("\xbf") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr8Zero) {
+  Buffer.assign("\xd9\x00", 2);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadStr8One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xd9\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr8Max) {
+  std::string Result(UINT8_MAX, 'a');
+  Buffer = std::string("\xd9\xff") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr16Zero) {
+  Buffer.assign("\xda\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadStr16One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xda\x00\x01", 3) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr16Max) {
+  std::string Result(UINT16_MAX, 'a');
+  Buffer = std::string("\xda\xff\xff") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr32Zero) {
+  Buffer.assign("\xdb\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadStr32One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xdb\x00\x00\x00\x01", 5) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadStr32Max) {
+  std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
+  Buffer = std::string("\xdb\x00\x01\x00\x00", 5) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::String);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin8Zero) {
+  Buffer.assign("\xc4\x00", 2);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadBin8One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xc4\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin8Max) {
+  std::string Result(UINT8_MAX, 'a');
+  Buffer = std::string("\xc4\xff") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin16Zero) {
+  Buffer.assign("\xc5\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadBin16One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xc5\x00\x01", 3) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin16Max) {
+  std::string Result(UINT16_MAX, 'a');
+  Buffer = std::string("\xc5\xff\xff") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin32Zero) {
+  Buffer.assign("\xc6\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadBin32One) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xc6\x00\x00\x00\x01", 5) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadBin32Max) {
+  std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
+  Buffer = std::string("\xc6\x00\x01\x00\x00", 5) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Binary);
+  EXPECT_EQ(Obj.Raw, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixArrayZero) {
+  Buffer = "\x90";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadFixArrayOne) {
+  Buffer = "\x91";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadFixArrayMax) {
+  Buffer = "\x9f";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  // FixArray format's size is a 4 bit unsigned integer, so max is 1111 = 15
+  EXPECT_EQ(Obj.Length, 15u);
+}
+
+TEST_F(MsgPackReader, TestReadArray16Zero) {
+  Buffer.assign("\xdc\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadArray16One) {
+  Buffer.assign("\xdc\x00\x01", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadArray16Max) {
+  Buffer = "\xdc\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, static_cast<uint16_t>(UINT16_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadArray32Zero) {
+  Buffer.assign("\xdd\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadArray32One) {
+  Buffer.assign("\xdd\x00\x00\x00\x01", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadArray32Max) {
+  Buffer = "\xdd\xff\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Array);
+  EXPECT_EQ(Obj.Length, static_cast<uint32_t>(UINT32_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadFixMapZero) {
+  Buffer = "\x80";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadFixMapOne) {
+  Buffer = "\x81";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadFixMapMax) {
+  Buffer = "\x8f";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  // FixMap format's size is a 4 bit unsigned integer, so max is 1111 = 15
+  EXPECT_EQ(Obj.Length, 15u);
+}
+
+TEST_F(MsgPackReader, TestReadMap16Zero) {
+  Buffer.assign("\xde\x00\x00", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadMap16One) {
+  Buffer.assign("\xde\x00\x01", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadMap16Max) {
+  Buffer = "\xde\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, static_cast<uint16_t>(UINT16_MAX));
+}
+
+TEST_F(MsgPackReader, TestReadMap32Zero) {
+  Buffer.assign("\xdf\x00\x00\x00\x00", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 0u);
+}
+
+TEST_F(MsgPackReader, TestReadMap32One) {
+  Buffer.assign("\xdf\x00\x00\x00\x01", 5);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, 1u);
+}
+
+TEST_F(MsgPackReader, TestReadMap32Max) {
+  Buffer = "\xdf\xff\xff\xff\xff";
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Map);
+  EXPECT_EQ(Obj.Length, static_cast<uint32_t>(UINT32_MAX));
+}
+
+// FixExt formats are only available for these specific lengths: 1, 2, 4, 8, 16
+
+TEST_F(MsgPackReader, TestReadFixExt1) {
+  std::string Result(1, 'a');
+  Buffer = std::string("\xd4\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixExt2) {
+  std::string Result(2, 'a');
+  Buffer = std::string("\xd5\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixExt4) {
+  std::string Result(4, 'a');
+  Buffer = std::string("\xd6\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixExt8) {
+  std::string Result(8, 'a');
+  Buffer = std::string("\xd7\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadFixExt16) {
+  std::string Result(16, 'a');
+  Buffer = std::string("\xd8\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadExt8Min) {
+  // There are fix variants for sizes 1 and 2
+  Buffer.assign("\xc7\x00\x01", 3);
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, StringRef());
+}
+
+TEST_F(MsgPackReader, TestReadExt8Max) {
+  std::string Result(UINT8_MAX, 'a');
+  Buffer = std::string("\xc7\xff\x01", 3) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadExt16Min) {
+  std::string Result(static_cast<uint16_t>(UINT8_MAX) + 1, 'a');
+  Buffer = std::string("\xc8\x01\x00\x01", 4) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadExt16Max) {
+  std::string Result(UINT16_MAX, 'a');
+  Buffer = std::string("\xc8\xff\xff\x01") + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
+
+TEST_F(MsgPackReader, TestReadExt32Min) {
+  std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
+  Buffer = std::string("\xc9\x00\x01\x00\x00\x01", 6) + Result;
+  Reader MPReader(Buffer);
+  auto ContinueOrErr = MPReader.read(Obj);
+  EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
+  EXPECT_TRUE(*ContinueOrErr);
+  EXPECT_EQ(Obj.Kind, Type::Extension);
+  EXPECT_EQ(Obj.Extension.Type, 0x01);
+  EXPECT_EQ(Obj.Extension.Bytes, Result);
+}
diff --git a/llvm/unittests/BinaryFormat/MsgPackWriterTest.cpp b/llvm/unittests/BinaryFormat/MsgPackWriterTest.cpp
new file mode 100644
index 0000000..288ea6d
--- /dev/null
+++ b/llvm/unittests/BinaryFormat/MsgPackWriterTest.cpp
@@ -0,0 +1,523 @@
+//===- MsgPackWriterTest.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackWriter.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::msgpack;
+
+struct MsgPackWriter : testing::Test {
+  std::string Buffer;
+  llvm::raw_string_ostream OStream;
+  Writer MPWriter;
+
+  MsgPackWriter() : OStream(Buffer), MPWriter(OStream) {}
+};
+
+TEST_F(MsgPackWriter, TestWriteNil) {
+  MPWriter.writeNil();
+  EXPECT_EQ(OStream.str(), "\xc0");
+}
+
+TEST_F(MsgPackWriter, TestWriteBool) {
+  MPWriter.write(true);
+  MPWriter.write(false);
+  EXPECT_EQ(OStream.str(), "\xc3\xc2");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixPositiveInt) {
+  // FixPositiveInt form bitpattern starts with 0, so max FixPositiveInt
+  // is 01111111 = 127
+  for (uint64_t u = 0; u <= 127; ++u) {
+    Buffer.clear();
+    MPWriter.write(u);
+    std::string Output = OStream.str();
+    EXPECT_EQ(Output.size(), 1u);
+    EXPECT_EQ(Output.data()[0], static_cast<uint8_t>(u));
+  }
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt8Min) {
+  // See TestWriteFixPositiveInt for why 128 is the min non-fix Int8
+  uint64_t u = 128;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcc\x80");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt8) {
+  uint64_t u = 221;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcc\xdd");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt8Max) {
+  uint64_t u = UINT8_MAX;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcc\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt16Min) {
+  uint64_t u = static_cast<uint64_t>(UINT8_MAX) + 1;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), std::string("\xcd\x01\x00", 3));
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt16) {
+  uint64_t u = 43981;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcd\xab\xcd");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt16Max) {
+  uint64_t u = UINT16_MAX;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcd\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt32Min) {
+  uint64_t u = static_cast<uint64_t>(UINT16_MAX) + 1;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), std::string("\xce\x00\x01\x00\x00", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt32) {
+  uint64_t u = 2882400186;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xce\xab\xcd\xef\xba");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt32Max) {
+  uint64_t u = UINT32_MAX;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xce\xff\xff\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt64Min) {
+  uint64_t u = static_cast<uint64_t>(UINT32_MAX) + 1;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(),
+            std::string("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 9));
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt64) {
+  uint64_t u = 0x010203040506074a;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcf\x01\x02\x03\x04\x05\x06\x07\x4a");
+}
+
+TEST_F(MsgPackWriter, TestWriteUInt64Max) {
+  uint64_t u = UINT64_MAX;
+  MPWriter.write(u);
+  EXPECT_EQ(OStream.str(), "\xcf\xff\xff\xff\xff\xff\xff\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixNegativeInt) {
+  // Positive values will be written in a UInt form, so max FixNegativeInt is -1
+  //
+  // FixNegativeInt form bitpattern starts with 111, so min FixNegativeInt
+  // is 11100000 = -32
+  for (int64_t i = -1; i >= -32; --i) {
+    Buffer.clear();
+    MPWriter.write(i);
+    std::string Output = OStream.str();
+    EXPECT_EQ(Output.size(), 1u);
+    EXPECT_EQ(Output.data()[0], static_cast<int8_t>(i));
+  }
+}
+
+TEST_F(MsgPackWriter, TestWriteInt8Max) {
+  // See TestWriteFixNegativeInt for why -33 is the max non-fix Int8
+  int64_t i = -33;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd0\xdf");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt8) {
+  int64_t i = -40;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd0\xd8");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt8Min) {
+  int64_t i = INT8_MIN;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd0\x80");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt16Max) {
+  int64_t i = static_cast<int64_t>(INT8_MIN) - 1;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd1\xff\x7f");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt16) {
+  int64_t i = -4369;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd1\xee\xef");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt16Min) {
+  int64_t i = INT16_MIN;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), std::string("\xd1\x80\x00", 3));
+}
+
+TEST_F(MsgPackWriter, TestWriteInt32Max) {
+  int64_t i = static_cast<int64_t>(INT16_MIN) - 1;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd2\xff\xff\x7f\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt32) {
+  int64_t i = -286331153;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd2\xee\xee\xee\xef");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt32Min) {
+  int64_t i = INT32_MIN;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), std::string("\xd2\x80\x00\x00\x00", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteInt64Max) {
+  int64_t i = static_cast<int64_t>(INT32_MIN) - 1;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd3\xff\xff\xff\xff\x7f\xff\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt64) {
+  int64_t i = -1229782938247303441;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(), "\xd3\xee\xee\xee\xee\xee\xee\xee\xef");
+}
+
+TEST_F(MsgPackWriter, TestWriteInt64Min) {
+  int64_t i = INT64_MIN;
+  MPWriter.write(i);
+  EXPECT_EQ(OStream.str(),
+            std::string("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 9));
+}
+
+TEST_F(MsgPackWriter, TestWriteFloat32) {
+  float f = -3.6973142664068907e+28;
+  MPWriter.write(f);
+  EXPECT_EQ(OStream.str(), "\xca\xee\xee\xee\xef");
+}
+
+TEST_F(MsgPackWriter, TestWriteFloat64) {
+  double d = -2.2899894549927042e+226;
+  MPWriter.write(d);
+  EXPECT_EQ(OStream.str(), "\xcb\xee\xee\xee\xee\xee\xee\xee\xef");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixStrMin) {
+  std::string s;
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), "\xa0");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixStr) {
+  std::string s = "foo";
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), "\xa3"
+                           "foo");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixStrMax) {
+  // FixStr format's size is a 5 bit unsigned integer, so max is 11111 = 31
+  std::string s(31, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xbf") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr8Min) {
+  // See TestWriteFixStrMax for why 32 is the min non-fix Str8
+  std::string s(32, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xd9\x20") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr8) {
+  std::string s(33, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xd9\x21") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr8Max) {
+  std::string s(UINT8_MAX, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xd9\xff") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr16Min) {
+  std::string s(static_cast<uint64_t>(UINT8_MAX) + 1, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xda\x01\x00", 3) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr16) {
+  std::string s(511, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xda\x01\xff") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr16Max) {
+  std::string s(UINT16_MAX, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xda\xff\xff") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr32Min) {
+  std::string s(static_cast<uint64_t>(UINT16_MAX) + 1, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xdb\x00\x01\x00\x00", 5) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteStr32) {
+  std::string s(131071, 'a');
+  MPWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xdb\x00\x01\xff\xff", 5) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin8Min) {
+  std::string s;
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc4\x00", 2) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin8) {
+  std::string s(5, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc4\x05") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin8Max) {
+  std::string s(UINT8_MAX, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc4\xff") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin16Min) {
+  std::string s(static_cast<uint64_t>(UINT8_MAX) + 1, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc5\x01\x00", 3) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin16) {
+  std::string s(511, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), "\xc5\x01\xff" + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin16Max) {
+  std::string s(UINT16_MAX, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc5\xff\xff") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin32Min) {
+  std::string s(static_cast<uint64_t>(UINT16_MAX) + 1, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc6\x00\x01\x00\x00", 5) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteBin32) {
+  std::string s(131071, 'a');
+  MPWriter.write(MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc6\x00\x01\xff\xff", 5) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteFixArrayMin) {
+  MPWriter.writeArraySize(0);
+  EXPECT_EQ(OStream.str(), "\x90");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixArray) {
+  MPWriter.writeArraySize(4);
+  EXPECT_EQ(OStream.str(), "\x94");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixArrayMax) {
+  // FixArray format's size is a 4 bit unsigned integer, so max is 1111 = 15
+  MPWriter.writeArraySize(15);
+  EXPECT_EQ(OStream.str(), "\x9f");
+}
+
+TEST_F(MsgPackWriter, TestWriteArray16Min) {
+  // See TestWriteFixArrayMax for why 16 is the min non-fix Array16
+  MPWriter.writeArraySize(16);
+  EXPECT_EQ(OStream.str(), std::string("\xdc\x00\x10", 3));
+}
+
+TEST_F(MsgPackWriter, TestWriteArray16) {
+  MPWriter.writeArraySize(273);
+  EXPECT_EQ(OStream.str(), "\xdc\x01\x11");
+}
+
+TEST_F(MsgPackWriter, TestWriteArray16Max) {
+  MPWriter.writeArraySize(UINT16_MAX);
+  EXPECT_EQ(OStream.str(), "\xdc\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteArray32Min) {
+  MPWriter.writeArraySize(static_cast<uint64_t>(UINT16_MAX) + 1);
+  EXPECT_EQ(OStream.str(), std::string("\xdd\x00\x01\x00\x00", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteArray32) {
+  MPWriter.writeArraySize(131071);
+  EXPECT_EQ(OStream.str(), std::string("\xdd\x00\x01\xff\xff", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteArray32Max) {
+  MPWriter.writeArraySize(UINT32_MAX);
+  EXPECT_EQ(OStream.str(), "\xdd\xff\xff\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixMapMin) {
+  MPWriter.writeMapSize(0);
+  EXPECT_EQ(OStream.str(), "\x80");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixMap) {
+  MPWriter.writeMapSize(4);
+  EXPECT_EQ(OStream.str(), "\x84");
+}
+
+TEST_F(MsgPackWriter, TestWriteFixMapMax) {
+  // FixMap format's size is a 4 bit unsigned integer, so max is 1111 = 15
+  MPWriter.writeMapSize(15);
+  EXPECT_EQ(OStream.str(), "\x8f");
+}
+
+TEST_F(MsgPackWriter, TestWriteMap16Min) {
+  // See TestWriteFixMapMax for why 16 is the min non-fix Map16
+  MPWriter.writeMapSize(16);
+  EXPECT_EQ(OStream.str(), std::string("\xde\x00\x10", 3));
+}
+
+TEST_F(MsgPackWriter, TestWriteMap16) {
+  MPWriter.writeMapSize(273);
+  EXPECT_EQ(OStream.str(), "\xde\x01\x11");
+}
+
+TEST_F(MsgPackWriter, TestWriteMap16Max) {
+  MPWriter.writeMapSize(UINT16_MAX);
+  EXPECT_EQ(OStream.str(), "\xde\xff\xff");
+}
+
+TEST_F(MsgPackWriter, TestWriteMap32Min) {
+  MPWriter.writeMapSize(static_cast<uint64_t>(UINT16_MAX) + 1);
+  EXPECT_EQ(OStream.str(), std::string("\xdf\x00\x01\x00\x00", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteMap32) {
+  MPWriter.writeMapSize(131071);
+  EXPECT_EQ(OStream.str(), std::string("\xdf\x00\x01\xff\xff", 5));
+}
+
+TEST_F(MsgPackWriter, TestWriteMap32Max) {
+  MPWriter.writeMapSize(UINT32_MAX);
+  EXPECT_EQ(OStream.str(), std::string("\xdf\xff\xff\xff\xff", 5));
+}
+
+// FixExt formats are only available for these specific lengths: 1, 2, 4, 8, 16
+
+TEST_F(MsgPackWriter, TestWriteFixExt1) {
+  std::string s(1, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xd4\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteFixExt2) {
+  std::string s(2, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xd5\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteFixExt4) {
+  std::string s(4, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xd6\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteFixExt8) {
+  std::string s(8, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xd7\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteFixExt16) {
+  std::string s(16, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xd8\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt8Min) {
+  std::string s;
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc7\x00\x01", 3) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt8) {
+  std::string s(0x2a, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc7\x2a\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt8Max) {
+  std::string s(UINT8_MAX, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc7\xff\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt16Min) {
+  std::string s(static_cast<uint16_t>(UINT8_MAX) + 1, 'a');
+  MPWriter.writeExt(0x02, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc8\x01\x00\x02", 4) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt16) {
+  std::string s(273, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc8\x01\x11\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt16Max) {
+  std::string s(UINT16_MAX, 'a');
+  MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc8\xff\xff\x01") + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteExt32Min) {
+  std::string s(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
+  MPWriter.writeExt(0x02, MemoryBufferRef(s, ""));
+  EXPECT_EQ(OStream.str(), std::string("\xc9\x00\x01\x00\x00\x02", 6) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteCompatibleNoStr8) {
+  Writer CompatWriter(OStream, true);
+  std::string s(32, 'a');
+  CompatWriter.write(s);
+  EXPECT_EQ(OStream.str(), std::string("\xda\x00\x20", 3) + s);
+}
+
+TEST_F(MsgPackWriter, TestWriteCompatibleNoBin) {
+  Writer CompatWriter(OStream, true);
+  std::string s;
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+  EXPECT_DEATH(CompatWriter.write(MemoryBufferRef(s, "")), "compatible mode");
+#endif
+#endif
+}