10b57cec5SDimitry Andric //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements a MessagePack reader.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPackReader.h"
150b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPack.h"
160b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
17fe6060f1SDimitry Andric #include "llvm/Support/MathExtras.h"
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric using namespace llvm::support;
210b57cec5SDimitry Andric using namespace msgpack;
220b57cec5SDimitry Andric
Reader(MemoryBufferRef InputBuffer)230b57cec5SDimitry Andric Reader::Reader(MemoryBufferRef InputBuffer)
240b57cec5SDimitry Andric : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
250b57cec5SDimitry Andric End(InputBuffer.getBufferEnd()) {}
260b57cec5SDimitry Andric
Reader(StringRef Input)270b57cec5SDimitry Andric Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
280b57cec5SDimitry Andric
read(Object & Obj)290b57cec5SDimitry Andric Expected<bool> Reader::read(Object &Obj) {
300b57cec5SDimitry Andric if (Current == End)
310b57cec5SDimitry Andric return false;
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric uint8_t FB = static_cast<uint8_t>(*Current++);
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric switch (FB) {
360b57cec5SDimitry Andric case FirstByte::Nil:
370b57cec5SDimitry Andric Obj.Kind = Type::Nil;
380b57cec5SDimitry Andric return true;
390b57cec5SDimitry Andric case FirstByte::True:
400b57cec5SDimitry Andric Obj.Kind = Type::Boolean;
410b57cec5SDimitry Andric Obj.Bool = true;
420b57cec5SDimitry Andric return true;
430b57cec5SDimitry Andric case FirstByte::False:
440b57cec5SDimitry Andric Obj.Kind = Type::Boolean;
450b57cec5SDimitry Andric Obj.Bool = false;
460b57cec5SDimitry Andric return true;
470b57cec5SDimitry Andric case FirstByte::Int8:
480b57cec5SDimitry Andric Obj.Kind = Type::Int;
490b57cec5SDimitry Andric return readInt<int8_t>(Obj);
500b57cec5SDimitry Andric case FirstByte::Int16:
510b57cec5SDimitry Andric Obj.Kind = Type::Int;
520b57cec5SDimitry Andric return readInt<int16_t>(Obj);
530b57cec5SDimitry Andric case FirstByte::Int32:
540b57cec5SDimitry Andric Obj.Kind = Type::Int;
550b57cec5SDimitry Andric return readInt<int32_t>(Obj);
560b57cec5SDimitry Andric case FirstByte::Int64:
570b57cec5SDimitry Andric Obj.Kind = Type::Int;
580b57cec5SDimitry Andric return readInt<int64_t>(Obj);
590b57cec5SDimitry Andric case FirstByte::UInt8:
600b57cec5SDimitry Andric Obj.Kind = Type::UInt;
610b57cec5SDimitry Andric return readUInt<uint8_t>(Obj);
620b57cec5SDimitry Andric case FirstByte::UInt16:
630b57cec5SDimitry Andric Obj.Kind = Type::UInt;
640b57cec5SDimitry Andric return readUInt<uint16_t>(Obj);
650b57cec5SDimitry Andric case FirstByte::UInt32:
660b57cec5SDimitry Andric Obj.Kind = Type::UInt;
670b57cec5SDimitry Andric return readUInt<uint32_t>(Obj);
680b57cec5SDimitry Andric case FirstByte::UInt64:
690b57cec5SDimitry Andric Obj.Kind = Type::UInt;
700b57cec5SDimitry Andric return readUInt<uint64_t>(Obj);
710b57cec5SDimitry Andric case FirstByte::Float32:
720b57cec5SDimitry Andric Obj.Kind = Type::Float;
730b57cec5SDimitry Andric if (sizeof(float) > remainingSpace())
740b57cec5SDimitry Andric return make_error<StringError>(
750b57cec5SDimitry Andric "Invalid Float32 with insufficient payload",
760b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
77*06c3fb27SDimitry Andric Obj.Float =
78*06c3fb27SDimitry Andric llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current));
790b57cec5SDimitry Andric Current += sizeof(float);
800b57cec5SDimitry Andric return true;
810b57cec5SDimitry Andric case FirstByte::Float64:
820b57cec5SDimitry Andric Obj.Kind = Type::Float;
830b57cec5SDimitry Andric if (sizeof(double) > remainingSpace())
840b57cec5SDimitry Andric return make_error<StringError>(
850b57cec5SDimitry Andric "Invalid Float64 with insufficient payload",
860b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
87*06c3fb27SDimitry Andric Obj.Float =
88*06c3fb27SDimitry Andric llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current));
890b57cec5SDimitry Andric Current += sizeof(double);
900b57cec5SDimitry Andric return true;
910b57cec5SDimitry Andric case FirstByte::Str8:
920b57cec5SDimitry Andric Obj.Kind = Type::String;
930b57cec5SDimitry Andric return readRaw<uint8_t>(Obj);
940b57cec5SDimitry Andric case FirstByte::Str16:
950b57cec5SDimitry Andric Obj.Kind = Type::String;
960b57cec5SDimitry Andric return readRaw<uint16_t>(Obj);
970b57cec5SDimitry Andric case FirstByte::Str32:
980b57cec5SDimitry Andric Obj.Kind = Type::String;
990b57cec5SDimitry Andric return readRaw<uint32_t>(Obj);
1000b57cec5SDimitry Andric case FirstByte::Bin8:
1010b57cec5SDimitry Andric Obj.Kind = Type::Binary;
1020b57cec5SDimitry Andric return readRaw<uint8_t>(Obj);
1030b57cec5SDimitry Andric case FirstByte::Bin16:
1040b57cec5SDimitry Andric Obj.Kind = Type::Binary;
1050b57cec5SDimitry Andric return readRaw<uint16_t>(Obj);
1060b57cec5SDimitry Andric case FirstByte::Bin32:
1070b57cec5SDimitry Andric Obj.Kind = Type::Binary;
1080b57cec5SDimitry Andric return readRaw<uint32_t>(Obj);
1090b57cec5SDimitry Andric case FirstByte::Array16:
1100b57cec5SDimitry Andric Obj.Kind = Type::Array;
1110b57cec5SDimitry Andric return readLength<uint16_t>(Obj);
1120b57cec5SDimitry Andric case FirstByte::Array32:
1130b57cec5SDimitry Andric Obj.Kind = Type::Array;
1140b57cec5SDimitry Andric return readLength<uint32_t>(Obj);
1150b57cec5SDimitry Andric case FirstByte::Map16:
1160b57cec5SDimitry Andric Obj.Kind = Type::Map;
1170b57cec5SDimitry Andric return readLength<uint16_t>(Obj);
1180b57cec5SDimitry Andric case FirstByte::Map32:
1190b57cec5SDimitry Andric Obj.Kind = Type::Map;
1200b57cec5SDimitry Andric return readLength<uint32_t>(Obj);
1210b57cec5SDimitry Andric case FirstByte::FixExt1:
1220b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1230b57cec5SDimitry Andric return createExt(Obj, FixLen::Ext1);
1240b57cec5SDimitry Andric case FirstByte::FixExt2:
1250b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1260b57cec5SDimitry Andric return createExt(Obj, FixLen::Ext2);
1270b57cec5SDimitry Andric case FirstByte::FixExt4:
1280b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1290b57cec5SDimitry Andric return createExt(Obj, FixLen::Ext4);
1300b57cec5SDimitry Andric case FirstByte::FixExt8:
1310b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1320b57cec5SDimitry Andric return createExt(Obj, FixLen::Ext8);
1330b57cec5SDimitry Andric case FirstByte::FixExt16:
1340b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1350b57cec5SDimitry Andric return createExt(Obj, FixLen::Ext16);
1360b57cec5SDimitry Andric case FirstByte::Ext8:
1370b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1380b57cec5SDimitry Andric return readExt<uint8_t>(Obj);
1390b57cec5SDimitry Andric case FirstByte::Ext16:
1400b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1410b57cec5SDimitry Andric return readExt<uint16_t>(Obj);
1420b57cec5SDimitry Andric case FirstByte::Ext32:
1430b57cec5SDimitry Andric Obj.Kind = Type::Extension;
1440b57cec5SDimitry Andric return readExt<uint32_t>(Obj);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
1480b57cec5SDimitry Andric Obj.Kind = Type::Int;
1490b57cec5SDimitry Andric int8_t I;
1500b57cec5SDimitry Andric static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
1510b57cec5SDimitry Andric memcpy(&I, &FB, sizeof(FB));
1520b57cec5SDimitry Andric Obj.Int = I;
1530b57cec5SDimitry Andric return true;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
1570b57cec5SDimitry Andric Obj.Kind = Type::UInt;
1580b57cec5SDimitry Andric Obj.UInt = FB;
1590b57cec5SDimitry Andric return true;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric if ((FB & FixBitsMask::String) == FixBits::String) {
1630b57cec5SDimitry Andric Obj.Kind = Type::String;
1640b57cec5SDimitry Andric uint8_t Size = FB & ~FixBitsMask::String;
1650b57cec5SDimitry Andric return createRaw(Obj, Size);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric if ((FB & FixBitsMask::Array) == FixBits::Array) {
1690b57cec5SDimitry Andric Obj.Kind = Type::Array;
1700b57cec5SDimitry Andric Obj.Length = FB & ~FixBitsMask::Array;
1710b57cec5SDimitry Andric return true;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric if ((FB & FixBitsMask::Map) == FixBits::Map) {
1750b57cec5SDimitry Andric Obj.Kind = Type::Map;
1760b57cec5SDimitry Andric Obj.Length = FB & ~FixBitsMask::Map;
1770b57cec5SDimitry Andric return true;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric return make_error<StringError>(
1810b57cec5SDimitry Andric "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
readRaw(Object & Obj)1840b57cec5SDimitry Andric template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
1850b57cec5SDimitry Andric if (sizeof(T) > remainingSpace())
1860b57cec5SDimitry Andric return make_error<StringError>(
1870b57cec5SDimitry Andric "Invalid Raw with insufficient payload",
1880b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
1890b57cec5SDimitry Andric T Size = endian::read<T, Endianness>(Current);
1900b57cec5SDimitry Andric Current += sizeof(T);
1910b57cec5SDimitry Andric return createRaw(Obj, Size);
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
readInt(Object & Obj)1940b57cec5SDimitry Andric template <class T> Expected<bool> Reader::readInt(Object &Obj) {
1950b57cec5SDimitry Andric if (sizeof(T) > remainingSpace())
1960b57cec5SDimitry Andric return make_error<StringError>(
1970b57cec5SDimitry Andric "Invalid Int with insufficient payload",
1980b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
1990b57cec5SDimitry Andric Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
2000b57cec5SDimitry Andric Current += sizeof(T);
2010b57cec5SDimitry Andric return true;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric
readUInt(Object & Obj)2040b57cec5SDimitry Andric template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
2050b57cec5SDimitry Andric if (sizeof(T) > remainingSpace())
2060b57cec5SDimitry Andric return make_error<StringError>(
2070b57cec5SDimitry Andric "Invalid Int with insufficient payload",
2080b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2090b57cec5SDimitry Andric Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
2100b57cec5SDimitry Andric Current += sizeof(T);
2110b57cec5SDimitry Andric return true;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
readLength(Object & Obj)2140b57cec5SDimitry Andric template <class T> Expected<bool> Reader::readLength(Object &Obj) {
2150b57cec5SDimitry Andric if (sizeof(T) > remainingSpace())
2160b57cec5SDimitry Andric return make_error<StringError>(
2170b57cec5SDimitry Andric "Invalid Map/Array with invalid length",
2180b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2190b57cec5SDimitry Andric Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
2200b57cec5SDimitry Andric Current += sizeof(T);
2210b57cec5SDimitry Andric return true;
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
readExt(Object & Obj)2240b57cec5SDimitry Andric template <class T> Expected<bool> Reader::readExt(Object &Obj) {
2250b57cec5SDimitry Andric if (sizeof(T) > remainingSpace())
2260b57cec5SDimitry Andric return make_error<StringError>(
2270b57cec5SDimitry Andric "Invalid Ext with invalid length",
2280b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2290b57cec5SDimitry Andric T Size = endian::read<T, Endianness>(Current);
2300b57cec5SDimitry Andric Current += sizeof(T);
2310b57cec5SDimitry Andric return createExt(Obj, Size);
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric
createRaw(Object & Obj,uint32_t Size)2340b57cec5SDimitry Andric Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
2350b57cec5SDimitry Andric if (Size > remainingSpace())
2360b57cec5SDimitry Andric return make_error<StringError>(
2370b57cec5SDimitry Andric "Invalid Raw with insufficient payload",
2380b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2390b57cec5SDimitry Andric Obj.Raw = StringRef(Current, Size);
2400b57cec5SDimitry Andric Current += Size;
2410b57cec5SDimitry Andric return true;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric
createExt(Object & Obj,uint32_t Size)2440b57cec5SDimitry Andric Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
2450b57cec5SDimitry Andric if (Current == End)
2460b57cec5SDimitry Andric return make_error<StringError>(
2470b57cec5SDimitry Andric "Invalid Ext with no type",
2480b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2490b57cec5SDimitry Andric Obj.Extension.Type = *Current++;
2500b57cec5SDimitry Andric if (Size > remainingSpace())
2510b57cec5SDimitry Andric return make_error<StringError>(
2520b57cec5SDimitry Andric "Invalid Ext with insufficient payload",
2530b57cec5SDimitry Andric std::make_error_code(std::errc::invalid_argument));
2540b57cec5SDimitry Andric Obj.Extension.Bytes = StringRef(Current, Size);
2550b57cec5SDimitry Andric Current += Size;
2560b57cec5SDimitry Andric return true;
2570b57cec5SDimitry Andric }
258