1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[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
This commit is contained in:
Scott Linder 2018-08-22 21:42:50 +00:00
parent d02128f555
commit c46ffa9c82
10 changed files with 2361 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,8 @@
add_llvm_library(LLVMBinaryFormat add_llvm_library(LLVMBinaryFormat
Dwarf.cpp Dwarf.cpp
Magic.cpp Magic.cpp
MsgPackReader.cpp
MsgPackWriter.cpp
Wasm.cpp Wasm.cpp
ADDITIONAL_HEADER_DIRS ADDITIONAL_HEADER_DIRS

View File

@ -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;
}

View File

@ -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);
}

View File

@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(BinaryFormatTests add_llvm_unittest(BinaryFormatTests
DwarfTest.cpp DwarfTest.cpp
MachOTest.cpp MachOTest.cpp
MsgPackReaderTest.cpp
MsgPackWriterTest.cpp
TestFileMagic.cpp TestFileMagic.cpp
) )

View File

@ -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);
}

View File

@ -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
}