[llvm] r340457 - [BinaryFormat] Add MessagePack reader/writer
Scott Linder via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 22 14:42:50 PDT 2018
Author: scott.linder
Date: Wed Aug 22 14:42:50 2018
New Revision: 340457
URL: http://llvm.org/viewvc/llvm-project?rev=340457&view=rev
Log:
[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
Added:
llvm/trunk/include/llvm/BinaryFormat/MsgPack.def
llvm/trunk/include/llvm/BinaryFormat/MsgPack.h
llvm/trunk/include/llvm/BinaryFormat/MsgPackReader.h
llvm/trunk/include/llvm/BinaryFormat/MsgPackWriter.h
llvm/trunk/lib/BinaryFormat/MsgPackReader.cpp
llvm/trunk/lib/BinaryFormat/MsgPackWriter.cpp
llvm/trunk/unittests/BinaryFormat/MsgPackReaderTest.cpp
llvm/trunk/unittests/BinaryFormat/MsgPackWriterTest.cpp
Modified:
llvm/trunk/lib/BinaryFormat/CMakeLists.txt
llvm/trunk/unittests/BinaryFormat/CMakeLists.txt
Added: llvm/trunk/include/llvm/BinaryFormat/MsgPack.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MsgPack.def?rev=340457&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MsgPack.def (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MsgPack.def Wed Aug 22 14:42:50 2018
@@ -0,0 +1,108 @@
+//===- MsgPack.def - MessagePack definitions --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Macros for running through MessagePack enumerators.
+///
+//===----------------------------------------------------------------------===//
+
+#if !( \
+ defined HANDLE_MP_FIRST_BYTE || defined HANDLE_MP_FIX_BITS || \
+ defined HANDLE_MP_FIX_BITS_MASK || defined HANDLE_MP_FIX_MAX || \
+ defined HANDLE_MP_FIX_LEN || defined HANDLE_MP_FIX_MIN)
+#error "Missing macro definition of HANDLE_MP*"
+#endif
+
+#ifndef HANDLE_MP_FIRST_BYTE
+#define HANDLE_MP_FIRST_BYTE(ID, NAME)
+#endif
+
+#ifndef HANDLE_MP_FIX_BITS
+#define HANDLE_MP_FIX_BITS(ID, NAME)
+#endif
+
+#ifndef HANDLE_MP_FIX_BITS_MASK
+#define HANDLE_MP_FIX_BITS_MASK(ID, NAME)
+#endif
+
+#ifndef HANDLE_MP_FIX_MAX
+#define HANDLE_MP_FIX_MAX(ID, NAME)
+#endif
+
+#ifndef HANDLE_MP_FIX_LEN
+#define HANDLE_MP_FIX_LEN(ID, NAME)
+#endif
+
+#ifndef HANDLE_MP_FIX_MIN
+#define HANDLE_MP_FIX_MIN(ID, NAME)
+#endif
+
+HANDLE_MP_FIRST_BYTE(0xc0, Nil)
+HANDLE_MP_FIRST_BYTE(0xc2, False)
+HANDLE_MP_FIRST_BYTE(0xc3, True)
+HANDLE_MP_FIRST_BYTE(0xc4, Bin8)
+HANDLE_MP_FIRST_BYTE(0xc5, Bin16)
+HANDLE_MP_FIRST_BYTE(0xc6, Bin32)
+HANDLE_MP_FIRST_BYTE(0xc7, Ext8)
+HANDLE_MP_FIRST_BYTE(0xc8, Ext16)
+HANDLE_MP_FIRST_BYTE(0xc9, Ext32)
+HANDLE_MP_FIRST_BYTE(0xca, Float32)
+HANDLE_MP_FIRST_BYTE(0xcb, Float64)
+HANDLE_MP_FIRST_BYTE(0xcc, UInt8)
+HANDLE_MP_FIRST_BYTE(0xcd, UInt16)
+HANDLE_MP_FIRST_BYTE(0xce, UInt32)
+HANDLE_MP_FIRST_BYTE(0xcf, UInt64)
+HANDLE_MP_FIRST_BYTE(0xd0, Int8)
+HANDLE_MP_FIRST_BYTE(0xd1, Int16)
+HANDLE_MP_FIRST_BYTE(0xd2, Int32)
+HANDLE_MP_FIRST_BYTE(0xd3, Int64)
+HANDLE_MP_FIRST_BYTE(0xd4, FixExt1)
+HANDLE_MP_FIRST_BYTE(0xd5, FixExt2)
+HANDLE_MP_FIRST_BYTE(0xd6, FixExt4)
+HANDLE_MP_FIRST_BYTE(0xd7, FixExt8)
+HANDLE_MP_FIRST_BYTE(0xd8, FixExt16)
+HANDLE_MP_FIRST_BYTE(0xd9, Str8)
+HANDLE_MP_FIRST_BYTE(0xda, Str16)
+HANDLE_MP_FIRST_BYTE(0xdb, Str32)
+HANDLE_MP_FIRST_BYTE(0xdc, Array16)
+HANDLE_MP_FIRST_BYTE(0xdd, Array32)
+HANDLE_MP_FIRST_BYTE(0xde, Map16)
+HANDLE_MP_FIRST_BYTE(0xdf, Map32)
+
+HANDLE_MP_FIX_BITS(0x00, PositiveInt)
+HANDLE_MP_FIX_BITS(0x80, Map)
+HANDLE_MP_FIX_BITS(0x90, Array)
+HANDLE_MP_FIX_BITS(0xa0, String)
+HANDLE_MP_FIX_BITS(0xe0, NegativeInt)
+
+HANDLE_MP_FIX_BITS_MASK(0x80, PositiveInt)
+HANDLE_MP_FIX_BITS_MASK(0xf0, Map)
+HANDLE_MP_FIX_BITS_MASK(0xf0, Array)
+HANDLE_MP_FIX_BITS_MASK(0xe0, String)
+HANDLE_MP_FIX_BITS_MASK(0xe0, NegativeInt)
+
+HANDLE_MP_FIX_MAX(0x7f, PositiveInt)
+HANDLE_MP_FIX_MAX(0x0f, Map)
+HANDLE_MP_FIX_MAX(0x0f, Array)
+HANDLE_MP_FIX_MAX(0x1f, String)
+
+HANDLE_MP_FIX_LEN(0x01, Ext1)
+HANDLE_MP_FIX_LEN(0x02, Ext2)
+HANDLE_MP_FIX_LEN(0x04, Ext4)
+HANDLE_MP_FIX_LEN(0x08, Ext8)
+HANDLE_MP_FIX_LEN(0x10, Ext16)
+
+HANDLE_MP_FIX_MIN(-0x20, NegativeInt)
+
+#undef HANDLE_MP_FIRST_BYTE
+#undef HANDLE_MP_FIX_BITS
+#undef HANDLE_MP_FIX_BITS_MASK
+#undef HANDLE_MP_FIX_MAX
+#undef HANDLE_MP_FIX_LEN
+#undef HANDLE_MP_FIX_MIN
Added: llvm/trunk/include/llvm/BinaryFormat/MsgPack.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MsgPack.h?rev=340457&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MsgPack.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MsgPack.h Wed Aug 22 14:42:50 2018
@@ -0,0 +1,93 @@
+//===-- MsgPack.h - MessagePack Constants -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains constants used for implementing MessagePack support.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_MSGPACK_H
+#define LLVM_BINARYFORMAT_MSGPACK_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace msgpack {
+
+/// The endianness of all multi-byte encoded values in MessagePack.
+constexpr support::endianness Endianness = support::big;
+
+/// The first byte identifiers of MessagePack object formats.
+namespace FirstByte {
+#define HANDLE_MP_FIRST_BYTE(ID, NAME) constexpr uint8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+/// Most significant bits used to identify "Fix" variants in MessagePack.
+///
+/// For example, FixStr objects encode their size in the five least significant
+/// bits of their first byte, which is identified by the bit pattern "101" in
+/// the three most significant bits. So FixBits::String contains 0b10100000.
+///
+/// A corresponding mask of the bit pattern is found in \c FixBitsMask.
+namespace FixBits {
+#define HANDLE_MP_FIX_BITS(ID, NAME) constexpr uint8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+/// Mask of bits used to identify "Fix" variants in MessagePack.
+///
+/// For example, FixStr objects encode their size in the five least significant
+/// bits of their first byte, which is identified by the bit pattern "101" in
+/// the three most significant bits. So FixBitsMask::String contains
+/// 0b11100000.
+///
+/// The corresponding bit pattern to mask for is found in FixBits.
+namespace FixBitsMask {
+#define HANDLE_MP_FIX_BITS_MASK(ID, NAME) constexpr uint8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+/// The maximum value or size encodable in "Fix" variants of formats.
+///
+/// For example, FixStr objects encode their size in the five least significant
+/// bits of their first byte, so the largest encodable size is 0b00011111.
+namespace FixMax {
+#define HANDLE_MP_FIX_MAX(ID, NAME) constexpr uint8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+/// The exact size encodable in "Fix" variants of formats.
+///
+/// The only objects for which an exact size makes sense are of Extension type.
+///
+/// For example, FixExt4 stores an extension type containing exactly four bytes.
+namespace FixLen {
+#define HANDLE_MP_FIX_LEN(ID, NAME) constexpr uint8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+/// The minimum value or size encodable in "Fix" variants of formats.
+///
+/// The only object for which a minimum makes sense is a negative FixNum.
+///
+/// Negative FixNum objects encode their signed integer value in one byte, but
+/// they must have the pattern "111" as their three most significant bits. This
+/// means all values are negative, and the smallest representable value is
+/// 0b11100000.
+namespace FixMin {
+#define HANDLE_MP_FIX_MIN(ID, NAME) constexpr int8_t NAME = ID;
+#include "llvm/BinaryFormat/MsgPack.def"
+}
+
+} // end namespace msgpack
+} // end namespace llvm
+
+#endif // LLVM_BINARYFORMAT_MSGPACK_H
Added: llvm/trunk/include/llvm/BinaryFormat/MsgPackReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MsgPackReader.h?rev=340457&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MsgPackReader.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MsgPackReader.h Wed Aug 22 14:42:50 2018
@@ -0,0 +1,148 @@
+//===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This is a MessagePack reader.
+///
+/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
+/// standard.
+///
+/// Typical usage:
+/// \code
+/// StringRef input = GetInput();
+/// msgpack::Reader MPReader(input);
+/// msgpack::Object Obj;
+///
+/// while (MPReader.read(Obj)) {
+/// switch (Obj.Kind) {
+/// case msgpack::Type::Int:
+// // Use Obj.Int
+/// break;
+/// // ...
+/// }
+/// }
+/// \endcode
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MSGPACKREADER_H
+#define LLVM_SUPPORT_MSGPACKREADER_H
+
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace llvm {
+namespace msgpack {
+
+/// MessagePack types as defined in the standard, with the exception of Integer
+/// being divided into a signed Int and unsigned UInt variant in order to map
+/// directly to C++ types.
+///
+/// The types map onto corresponding union members of the \c Object struct.
+enum class Type : uint8_t {
+ Int,
+ UInt,
+ Nil,
+ Boolean,
+ Float,
+ String,
+ Binary,
+ Array,
+ Map,
+ Extension,
+};
+
+/// Extension types are composed of a user-defined type ID and an uninterpreted
+/// sequence of bytes.
+struct ExtensionType {
+ /// User-defined extension type.
+ int8_t Type;
+ /// Raw bytes of the extension object.
+ StringRef Bytes;
+};
+
+/// MessagePack object, represented as a tagged union of C++ types.
+///
+/// All types except \c Type::Nil (which has only one value, and so is
+/// completely represented by the \c Kind itself) map to a exactly one union
+/// member.
+struct Object {
+ Type Kind;
+ union {
+ /// Value for \c Type::Int.
+ int64_t Int;
+ /// Value for \c Type::Uint.
+ uint64_t UInt;
+ /// Value for \c Type::Boolean.
+ bool Bool;
+ /// Value for \c Type::Float.
+ double Float;
+ /// Value for \c Type::String and \c Type::Binary.
+ StringRef Raw;
+ /// Value for \c Type::Array and \c Type::Map.
+ size_t Length;
+ /// Value for \c Type::Extension.
+ ExtensionType Extension;
+ };
+
+ Object() : Kind(Type::Int), Int(0) {}
+};
+
+/// Reads MessagePack objects from memory, one at a time.
+class Reader {
+public:
+ /// Construct a reader, keeping a reference to the \p InputBuffer.
+ Reader(MemoryBufferRef InputBuffer);
+ /// Construct a reader, keeping a reference to the \p Input.
+ Reader(StringRef Input);
+
+ Reader(const Reader &) = delete;
+ Reader &operator=(const Reader &) = delete;
+
+ /// Read one object from the input buffer, advancing past it.
+ ///
+ /// The \p Obj is updated with the kind of the object read, and the
+ /// corresponding union member is updated.
+ ///
+ /// For the collection objects (Array and Map), only the length is read, and
+ /// the caller must make and additional \c N calls (in the case of Array) or
+ /// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection
+ /// elements.
+ ///
+ /// \param [out] Obj filled with next object on success.
+ ///
+ /// \returns true when object successfully read, false when at end of
+ /// input (and so \p Obj was not updated), otherwise an error.
+ Expected<bool> read(Object &Obj);
+
+private:
+ MemoryBufferRef InputBuffer;
+ StringRef::iterator Current;
+ StringRef::iterator End;
+
+ size_t remainingSpace() {
+ // The rest of the code maintains the invariant that End >= Current, so
+ // that this cast is always defined behavior.
+ return static_cast<size_t>(End - Current);
+ }
+
+ template <class T> Expected<bool> readRaw(Object &Obj);
+ template <class T> Expected<bool> readInt(Object &Obj);
+ template <class T> Expected<bool> readUInt(Object &Obj);
+ template <class T> Expected<bool> readLength(Object &Obj);
+ template <class T> Expected<bool> readExt(Object &Obj);
+ Expected<bool> createRaw(Object &Obj, uint32_t Size);
+ Expected<bool> createExt(Object &Obj, uint32_t Size);
+};
+
+} // end namespace msgpack
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_MSGPACKREADER_H
Added: llvm/trunk/include/llvm/BinaryFormat/MsgPackWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MsgPackWriter.h?rev=340457&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MsgPackWriter.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MsgPackWriter.h Wed Aug 22 14:42:50 2018
@@ -0,0 +1,131 @@
+//===- MsgPackWriter.h - Simple MsgPack writer ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains a MessagePack writer.
+///
+/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
+/// specification.
+///
+/// Typical usage:
+/// \code
+/// raw_ostream output = GetOutputStream();
+/// msgpack::Writer MPWriter(output);
+/// MPWriter.writeNil();
+/// MPWriter.write(false);
+/// MPWriter.write("string");
+/// // ...
+/// \endcode
+///
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MSGPACKPARSER_H
+#define LLVM_SUPPORT_MSGPACKPARSER_H
+
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace msgpack {
+
+/// Writes MessagePack objects to an output stream, one at a time.
+class Writer {
+public:
+ /// Construct a writer, optionally enabling "Compatibility Mode" as defined
+ /// in the MessagePack specification.
+ ///
+ /// When in \p Compatible mode, the writer will write \c Str16 formats
+ /// instead of \c Str8 formats, and will refuse to write any \c Bin formats.
+ ///
+ /// \param OS stream to output MessagePack objects to.
+ /// \param Compatible when set, write in "Compatibility Mode".
+ Writer(raw_ostream &OS, bool Compatible = false);
+
+ Writer(const Writer &) = delete;
+ Writer &operator=(const Writer &) = delete;
+
+ /// Write a \em Nil to the output stream.
+ ///
+ /// The output will be the \em nil format.
+ void writeNil();
+
+ /// Write a \em Boolean to the output stream.
+ ///
+ /// The output will be a \em bool format.
+ void write(bool b);
+
+ /// Write a signed integer to the output stream.
+ ///
+ /// The output will be in the smallest possible \em int format.
+ ///
+ /// The format chosen may be for an unsigned integer.
+ void write(int64_t i);
+
+ /// Write an unsigned integer to the output stream.
+ ///
+ /// The output will be in the smallest possible \em int format.
+ void write(uint64_t u);
+
+ /// Write a floating point number to the output stream.
+ ///
+ /// The output will be in the smallest possible \em float format.
+ void write(double d);
+
+ /// Write a string to the output stream.
+ ///
+ /// The output will be in the smallest possible \em str format.
+ void write(StringRef s);
+
+ /// Write a memory buffer to the output stream.
+ ///
+ /// The output will be in the smallest possible \em bin format.
+ ///
+ /// \warning Do not use this overload if in \c Compatible mode.
+ void write(MemoryBufferRef Buffer);
+
+ /// Write the header for an \em Array of the given size.
+ ///
+ /// The output will be in the smallest possible \em array format.
+ //
+ /// The header contains an identifier for the \em array format used, as well
+ /// as an encoding of the size of the array.
+ ///
+ /// N.B. The caller must subsequently call \c Write an additional \p Size
+ /// times to complete the array.
+ void writeArraySize(uint32_t Size);
+
+ /// Write the header for a \em Map of the given size.
+ ///
+ /// The output will be in the smallest possible \em map format.
+ //
+ /// The header contains an identifier for the \em map format used, as well
+ /// as an encoding of the size of the map.
+ ///
+ /// N.B. The caller must subsequently call \c Write and additional \c Size*2
+ /// times to complete the map. Each even numbered call to \c Write defines a
+ /// new key, and each odd numbered call defines the previous key's value.
+ void writeMapSize(uint32_t Size);
+
+ /// Write a typed memory buffer (an extension type) to the output stream.
+ ///
+ /// The output will be in the smallest possible \em ext format.
+ void writeExt(int8_t Type, MemoryBufferRef Buffer);
+
+private:
+ support::endian::Writer EW;
+ bool Compatible;
+};
+
+} // end namespace msgpack
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_MSGPACKPARSER_H
Modified: llvm/trunk/lib/BinaryFormat/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/CMakeLists.txt?rev=340457&r1=340456&r2=340457&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/CMakeLists.txt (original)
+++ llvm/trunk/lib/BinaryFormat/CMakeLists.txt Wed Aug 22 14:42:50 2018
@@ -1,6 +1,8 @@
add_llvm_library(LLVMBinaryFormat
Dwarf.cpp
Magic.cpp
+ MsgPackReader.cpp
+ MsgPackWriter.cpp
Wasm.cpp
ADDITIONAL_HEADER_DIRS
Added: llvm/trunk/lib/BinaryFormat/MsgPackReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/MsgPackReader.cpp?rev=340457&view=auto
==============================================================================
--- llvm/trunk/lib/BinaryFormat/MsgPackReader.cpp (added)
+++ llvm/trunk/lib/BinaryFormat/MsgPackReader.cpp Wed Aug 22 14:42:50 2018
@@ -0,0 +1,255 @@
+//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack reader.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackReader.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace msgpack;
+
+Reader::Reader(MemoryBufferRef InputBuffer)
+ : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
+ End(InputBuffer.getBufferEnd()) {}
+
+Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
+
+Expected<bool> Reader::read(Object &Obj) {
+ if (Current == End)
+ return false;
+
+ uint8_t FB = static_cast<uint8_t>(*Current++);
+
+ switch (FB) {
+ case FirstByte::Nil:
+ Obj.Kind = Type::Nil;
+ return true;
+ case FirstByte::True:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = true;
+ return true;
+ case FirstByte::False:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = false;
+ return true;
+ case FirstByte::Int8:
+ Obj.Kind = Type::Int;
+ return readInt<int8_t>(Obj);
+ case FirstByte::Int16:
+ Obj.Kind = Type::Int;
+ return readInt<int16_t>(Obj);
+ case FirstByte::Int32:
+ Obj.Kind = Type::Int;
+ return readInt<int32_t>(Obj);
+ case FirstByte::Int64:
+ Obj.Kind = Type::Int;
+ return readInt<int64_t>(Obj);
+ case FirstByte::UInt8:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint8_t>(Obj);
+ case FirstByte::UInt16:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint16_t>(Obj);
+ case FirstByte::UInt32:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint32_t>(Obj);
+ case FirstByte::UInt64:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint64_t>(Obj);
+ case FirstByte::Float32:
+ Obj.Kind = Type::Float;
+ if (sizeof(float) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float32 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
+ Current += sizeof(float);
+ return true;
+ case FirstByte::Float64:
+ Obj.Kind = Type::Float;
+ if (sizeof(double) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float64 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
+ Current += sizeof(double);
+ return true;
+ case FirstByte::Str8:
+ Obj.Kind = Type::String;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Str16:
+ Obj.Kind = Type::String;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Str32:
+ Obj.Kind = Type::String;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Bin8:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Bin16:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Bin32:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Array16:
+ Obj.Kind = Type::Array;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Array32:
+ Obj.Kind = Type::Array;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::Map16:
+ Obj.Kind = Type::Map;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Map32:
+ Obj.Kind = Type::Map;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::FixExt1:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext1);
+ case FirstByte::FixExt2:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext2);
+ case FirstByte::FixExt4:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext4);
+ case FirstByte::FixExt8:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext8);
+ case FirstByte::FixExt16:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext16);
+ case FirstByte::Ext8:
+ Obj.Kind = Type::Extension;
+ return readExt<uint8_t>(Obj);
+ case FirstByte::Ext16:
+ Obj.Kind = Type::Extension;
+ return readExt<uint16_t>(Obj);
+ case FirstByte::Ext32:
+ Obj.Kind = Type::Extension;
+ return readExt<uint32_t>(Obj);
+ }
+
+ if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
+ Obj.Kind = Type::Int;
+ int8_t I;
+ static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
+ memcpy(&I, &FB, sizeof(FB));
+ Obj.Int = I;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
+ Obj.Kind = Type::UInt;
+ Obj.UInt = FB;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::String) == FixBits::String) {
+ Obj.Kind = Type::String;
+ uint8_t Size = FB & ~FixBitsMask::String;
+ return createRaw(Obj, Size);
+ }
+
+ if ((FB & FixBitsMask::Array) == FixBits::Array) {
+ Obj.Kind = Type::Array;
+ Obj.Length = FB & ~FixBitsMask::Array;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::Map) == FixBits::Map) {
+ Obj.Kind = Type::Map;
+ Obj.Length = FB & ~FixBitsMask::Map;
+ return true;
+ }
+
+ return make_error<StringError>(
+ "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
+}
+
+template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createRaw(Obj, Size);
+}
+
+template <class T> Expected<bool> Reader::readInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readLength(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Map/Array with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readExt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createExt(Obj, Size);
+}
+
+Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Raw = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}
+
+Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
+ if (Current == End)
+ return make_error<StringError>(
+ "Invalid Ext with no type",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Type = *Current++;
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Bytes = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}
Added: llvm/trunk/lib/BinaryFormat/MsgPackWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/MsgPackWriter.cpp?rev=340457&view=auto
==============================================================================
--- llvm/trunk/lib/BinaryFormat/MsgPackWriter.cpp (added)
+++ llvm/trunk/lib/BinaryFormat/MsgPackWriter.cpp Wed Aug 22 14:42:50 2018
@@ -0,0 +1,208 @@
+//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack writer.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackWriter.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+Writer::Writer(raw_ostream &OS, bool Compatible)
+ : EW(OS, Endianness), Compatible(Compatible) {}
+
+void Writer::writeNil() { EW.write(FirstByte::Nil); }
+
+void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
+
+void Writer::write(int64_t i) {
+ if (i >= 0) {
+ write(static_cast<uint64_t>(i));
+ return;
+ }
+
+ if (i >= FixMin::NegativeInt) {
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT8_MIN) {
+ EW.write(FirstByte::Int8);
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT16_MIN) {
+ EW.write(FirstByte::Int16);
+ EW.write(static_cast<int16_t>(i));
+ return;
+ }
+
+ if (i >= INT32_MIN) {
+ EW.write(FirstByte::Int32);
+ EW.write(static_cast<int32_t>(i));
+ return;
+ }
+
+ EW.write(FirstByte::Int64);
+ EW.write(i);
+}
+
+void Writer::write(uint64_t u) {
+ if (u <= FixMax::PositiveInt) {
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT8_MAX) {
+ EW.write(FirstByte::UInt8);
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT16_MAX) {
+ EW.write(FirstByte::UInt16);
+ EW.write(static_cast<uint16_t>(u));
+ return;
+ }
+
+ if (u <= UINT32_MAX) {
+ EW.write(FirstByte::UInt32);
+ EW.write(static_cast<uint32_t>(u));
+ return;
+ }
+
+ EW.write(FirstByte::UInt64);
+ EW.write(u);
+}
+
+void Writer::write(double d) {
+ // If no loss of precision, encode as a Float32.
+ float f = static_cast<float>(d);
+ if (static_cast<double>(f) == d) {
+ EW.write(FirstByte::Float32);
+ EW.write(f);
+ } else {
+ EW.write(FirstByte::Float64);
+ EW.write(d);
+ }
+}
+
+void Writer::write(StringRef s) {
+ size_t Size = s.size();
+
+ if (Size <= FixMax::String)
+ EW.write(static_cast<uint8_t>(FixBits::String | Size));
+ else if (!Compatible && Size <= UINT8_MAX) {
+ EW.write(FirstByte::Str8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Str16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "String object too long to be encoded");
+ EW.write(FirstByte::Str32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS << s;
+}
+
+void Writer::write(MemoryBufferRef Buffer) {
+ assert(!Compatible && "Attempt to write Bin format in compatible mode");
+
+ size_t Size = Buffer.getBufferSize();
+
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Bin8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Bin16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
+ EW.write(FirstByte::Bin32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}
+
+void Writer::writeArraySize(uint32_t Size) {
+ if (Size <= FixMax::Array) {
+ EW.write(static_cast<uint8_t>(FixBits::Array | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Array16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Array32);
+ EW.write(Size);
+}
+
+void Writer::writeMapSize(uint32_t Size) {
+ if (Size <= FixMax::Map) {
+ EW.write(static_cast<uint8_t>(FixBits::Map | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Map16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Map32);
+ EW.write(Size);
+}
+
+void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
+ size_t Size = Buffer.getBufferSize();
+
+ switch (Size) {
+ case FixLen::Ext1:
+ EW.write(FirstByte::FixExt1);
+ break;
+ case FixLen::Ext2:
+ EW.write(FirstByte::FixExt2);
+ break;
+ case FixLen::Ext4:
+ EW.write(FirstByte::FixExt4);
+ break;
+ case FixLen::Ext8:
+ EW.write(FirstByte::FixExt8);
+ break;
+ case FixLen::Ext16:
+ EW.write(FirstByte::FixExt16);
+ break;
+ default:
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Ext8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Ext16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
+ EW.write(FirstByte::Ext32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+ }
+
+ EW.write(Type);
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}
Modified: llvm/trunk/unittests/BinaryFormat/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/CMakeLists.txt?rev=340457&r1=340456&r2=340457&view=diff
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/CMakeLists.txt (original)
+++ llvm/trunk/unittests/BinaryFormat/CMakeLists.txt Wed Aug 22 14:42:50 2018
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(BinaryFormatTests
DwarfTest.cpp
MachOTest.cpp
+ MsgPackReaderTest.cpp
+ MsgPackWriterTest.cpp
TestFileMagic.cpp
)
Added: llvm/trunk/unittests/BinaryFormat/MsgPackReaderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/MsgPackReaderTest.cpp?rev=340457&view=auto
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/MsgPackReaderTest.cpp (added)
+++ llvm/trunk/unittests/BinaryFormat/MsgPackReaderTest.cpp Wed Aug 22 14:42:50 2018
@@ -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);
+}
Added: llvm/trunk/unittests/BinaryFormat/MsgPackWriterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/MsgPackWriterTest.cpp?rev=340457&view=auto
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/MsgPackWriterTest.cpp (added)
+++ llvm/trunk/unittests/BinaryFormat/MsgPackWriterTest.cpp Wed Aug 22 14:42:50 2018
@@ -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
+}
More information about the llvm-commits
mailing list