120f9cd88SScott Linder //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
220f9cd88SScott Linder //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
620f9cd88SScott Linder //
720f9cd88SScott Linder //===----------------------------------------------------------------------===//
820f9cd88SScott Linder ///
920f9cd88SScott Linder /// \file
1020f9cd88SScott Linder /// This file implements a MessagePack reader.
1120f9cd88SScott Linder ///
1220f9cd88SScott Linder //===----------------------------------------------------------------------===//
1320f9cd88SScott Linder
1420f9cd88SScott Linder #include "llvm/BinaryFormat/MsgPackReader.h"
1520f9cd88SScott Linder #include "llvm/BinaryFormat/MsgPack.h"
1620f9cd88SScott Linder #include "llvm/Support/Endian.h"
17*24b9bc84SSimon Pilgrim #include "llvm/Support/MathExtras.h"
1820f9cd88SScott Linder
1920f9cd88SScott Linder using namespace llvm;
2020f9cd88SScott Linder using namespace llvm::support;
2120f9cd88SScott Linder using namespace msgpack;
2220f9cd88SScott Linder
Reader(MemoryBufferRef InputBuffer)2320f9cd88SScott Linder Reader::Reader(MemoryBufferRef InputBuffer)
2420f9cd88SScott Linder : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
2520f9cd88SScott Linder End(InputBuffer.getBufferEnd()) {}
2620f9cd88SScott Linder
Reader(StringRef Input)2720f9cd88SScott Linder Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
2820f9cd88SScott Linder
read(Object & Obj)2920f9cd88SScott Linder Expected<bool> Reader::read(Object &Obj) {
3020f9cd88SScott Linder if (Current == End)
3120f9cd88SScott Linder return false;
3220f9cd88SScott Linder
3320f9cd88SScott Linder uint8_t FB = static_cast<uint8_t>(*Current++);
3420f9cd88SScott Linder
3520f9cd88SScott Linder switch (FB) {
3620f9cd88SScott Linder case FirstByte::Nil:
3720f9cd88SScott Linder Obj.Kind = Type::Nil;
3820f9cd88SScott Linder return true;
3920f9cd88SScott Linder case FirstByte::True:
4020f9cd88SScott Linder Obj.Kind = Type::Boolean;
4120f9cd88SScott Linder Obj.Bool = true;
4220f9cd88SScott Linder return true;
4320f9cd88SScott Linder case FirstByte::False:
4420f9cd88SScott Linder Obj.Kind = Type::Boolean;
4520f9cd88SScott Linder Obj.Bool = false;
4620f9cd88SScott Linder return true;
4720f9cd88SScott Linder case FirstByte::Int8:
4820f9cd88SScott Linder Obj.Kind = Type::Int;
4920f9cd88SScott Linder return readInt<int8_t>(Obj);
5020f9cd88SScott Linder case FirstByte::Int16:
5120f9cd88SScott Linder Obj.Kind = Type::Int;
5220f9cd88SScott Linder return readInt<int16_t>(Obj);
5320f9cd88SScott Linder case FirstByte::Int32:
5420f9cd88SScott Linder Obj.Kind = Type::Int;
5520f9cd88SScott Linder return readInt<int32_t>(Obj);
5620f9cd88SScott Linder case FirstByte::Int64:
5720f9cd88SScott Linder Obj.Kind = Type::Int;
5820f9cd88SScott Linder return readInt<int64_t>(Obj);
5920f9cd88SScott Linder case FirstByte::UInt8:
6020f9cd88SScott Linder Obj.Kind = Type::UInt;
6120f9cd88SScott Linder return readUInt<uint8_t>(Obj);
6220f9cd88SScott Linder case FirstByte::UInt16:
6320f9cd88SScott Linder Obj.Kind = Type::UInt;
6420f9cd88SScott Linder return readUInt<uint16_t>(Obj);
6520f9cd88SScott Linder case FirstByte::UInt32:
6620f9cd88SScott Linder Obj.Kind = Type::UInt;
6720f9cd88SScott Linder return readUInt<uint32_t>(Obj);
6820f9cd88SScott Linder case FirstByte::UInt64:
6920f9cd88SScott Linder Obj.Kind = Type::UInt;
7020f9cd88SScott Linder return readUInt<uint64_t>(Obj);
7120f9cd88SScott Linder case FirstByte::Float32:
7220f9cd88SScott Linder Obj.Kind = Type::Float;
7320f9cd88SScott Linder if (sizeof(float) > remainingSpace())
7420f9cd88SScott Linder return make_error<StringError>(
7520f9cd88SScott Linder "Invalid Float32 with insufficient payload",
7620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
7720f9cd88SScott Linder Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
7820f9cd88SScott Linder Current += sizeof(float);
7920f9cd88SScott Linder return true;
8020f9cd88SScott Linder case FirstByte::Float64:
8120f9cd88SScott Linder Obj.Kind = Type::Float;
8220f9cd88SScott Linder if (sizeof(double) > remainingSpace())
8320f9cd88SScott Linder return make_error<StringError>(
8420f9cd88SScott Linder "Invalid Float64 with insufficient payload",
8520f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
8620f9cd88SScott Linder Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
8720f9cd88SScott Linder Current += sizeof(double);
8820f9cd88SScott Linder return true;
8920f9cd88SScott Linder case FirstByte::Str8:
9020f9cd88SScott Linder Obj.Kind = Type::String;
9120f9cd88SScott Linder return readRaw<uint8_t>(Obj);
9220f9cd88SScott Linder case FirstByte::Str16:
9320f9cd88SScott Linder Obj.Kind = Type::String;
9420f9cd88SScott Linder return readRaw<uint16_t>(Obj);
9520f9cd88SScott Linder case FirstByte::Str32:
9620f9cd88SScott Linder Obj.Kind = Type::String;
9720f9cd88SScott Linder return readRaw<uint32_t>(Obj);
9820f9cd88SScott Linder case FirstByte::Bin8:
9920f9cd88SScott Linder Obj.Kind = Type::Binary;
10020f9cd88SScott Linder return readRaw<uint8_t>(Obj);
10120f9cd88SScott Linder case FirstByte::Bin16:
10220f9cd88SScott Linder Obj.Kind = Type::Binary;
10320f9cd88SScott Linder return readRaw<uint16_t>(Obj);
10420f9cd88SScott Linder case FirstByte::Bin32:
10520f9cd88SScott Linder Obj.Kind = Type::Binary;
10620f9cd88SScott Linder return readRaw<uint32_t>(Obj);
10720f9cd88SScott Linder case FirstByte::Array16:
10820f9cd88SScott Linder Obj.Kind = Type::Array;
10920f9cd88SScott Linder return readLength<uint16_t>(Obj);
11020f9cd88SScott Linder case FirstByte::Array32:
11120f9cd88SScott Linder Obj.Kind = Type::Array;
11220f9cd88SScott Linder return readLength<uint32_t>(Obj);
11320f9cd88SScott Linder case FirstByte::Map16:
11420f9cd88SScott Linder Obj.Kind = Type::Map;
11520f9cd88SScott Linder return readLength<uint16_t>(Obj);
11620f9cd88SScott Linder case FirstByte::Map32:
11720f9cd88SScott Linder Obj.Kind = Type::Map;
11820f9cd88SScott Linder return readLength<uint32_t>(Obj);
11920f9cd88SScott Linder case FirstByte::FixExt1:
12020f9cd88SScott Linder Obj.Kind = Type::Extension;
12120f9cd88SScott Linder return createExt(Obj, FixLen::Ext1);
12220f9cd88SScott Linder case FirstByte::FixExt2:
12320f9cd88SScott Linder Obj.Kind = Type::Extension;
12420f9cd88SScott Linder return createExt(Obj, FixLen::Ext2);
12520f9cd88SScott Linder case FirstByte::FixExt4:
12620f9cd88SScott Linder Obj.Kind = Type::Extension;
12720f9cd88SScott Linder return createExt(Obj, FixLen::Ext4);
12820f9cd88SScott Linder case FirstByte::FixExt8:
12920f9cd88SScott Linder Obj.Kind = Type::Extension;
13020f9cd88SScott Linder return createExt(Obj, FixLen::Ext8);
13120f9cd88SScott Linder case FirstByte::FixExt16:
13220f9cd88SScott Linder Obj.Kind = Type::Extension;
13320f9cd88SScott Linder return createExt(Obj, FixLen::Ext16);
13420f9cd88SScott Linder case FirstByte::Ext8:
13520f9cd88SScott Linder Obj.Kind = Type::Extension;
13620f9cd88SScott Linder return readExt<uint8_t>(Obj);
13720f9cd88SScott Linder case FirstByte::Ext16:
13820f9cd88SScott Linder Obj.Kind = Type::Extension;
13920f9cd88SScott Linder return readExt<uint16_t>(Obj);
14020f9cd88SScott Linder case FirstByte::Ext32:
14120f9cd88SScott Linder Obj.Kind = Type::Extension;
14220f9cd88SScott Linder return readExt<uint32_t>(Obj);
14320f9cd88SScott Linder }
14420f9cd88SScott Linder
14520f9cd88SScott Linder if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
14620f9cd88SScott Linder Obj.Kind = Type::Int;
14720f9cd88SScott Linder int8_t I;
14820f9cd88SScott Linder static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
14920f9cd88SScott Linder memcpy(&I, &FB, sizeof(FB));
15020f9cd88SScott Linder Obj.Int = I;
15120f9cd88SScott Linder return true;
15220f9cd88SScott Linder }
15320f9cd88SScott Linder
15420f9cd88SScott Linder if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
15520f9cd88SScott Linder Obj.Kind = Type::UInt;
15620f9cd88SScott Linder Obj.UInt = FB;
15720f9cd88SScott Linder return true;
15820f9cd88SScott Linder }
15920f9cd88SScott Linder
16020f9cd88SScott Linder if ((FB & FixBitsMask::String) == FixBits::String) {
16120f9cd88SScott Linder Obj.Kind = Type::String;
16220f9cd88SScott Linder uint8_t Size = FB & ~FixBitsMask::String;
16320f9cd88SScott Linder return createRaw(Obj, Size);
16420f9cd88SScott Linder }
16520f9cd88SScott Linder
16620f9cd88SScott Linder if ((FB & FixBitsMask::Array) == FixBits::Array) {
16720f9cd88SScott Linder Obj.Kind = Type::Array;
16820f9cd88SScott Linder Obj.Length = FB & ~FixBitsMask::Array;
16920f9cd88SScott Linder return true;
17020f9cd88SScott Linder }
17120f9cd88SScott Linder
17220f9cd88SScott Linder if ((FB & FixBitsMask::Map) == FixBits::Map) {
17320f9cd88SScott Linder Obj.Kind = Type::Map;
17420f9cd88SScott Linder Obj.Length = FB & ~FixBitsMask::Map;
17520f9cd88SScott Linder return true;
17620f9cd88SScott Linder }
17720f9cd88SScott Linder
17820f9cd88SScott Linder return make_error<StringError>(
17920f9cd88SScott Linder "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
18020f9cd88SScott Linder }
18120f9cd88SScott Linder
readRaw(Object & Obj)18220f9cd88SScott Linder template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
18320f9cd88SScott Linder if (sizeof(T) > remainingSpace())
18420f9cd88SScott Linder return make_error<StringError>(
18520f9cd88SScott Linder "Invalid Raw with insufficient payload",
18620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
18720f9cd88SScott Linder T Size = endian::read<T, Endianness>(Current);
18820f9cd88SScott Linder Current += sizeof(T);
18920f9cd88SScott Linder return createRaw(Obj, Size);
19020f9cd88SScott Linder }
19120f9cd88SScott Linder
readInt(Object & Obj)19220f9cd88SScott Linder template <class T> Expected<bool> Reader::readInt(Object &Obj) {
19320f9cd88SScott Linder if (sizeof(T) > remainingSpace())
19420f9cd88SScott Linder return make_error<StringError>(
19520f9cd88SScott Linder "Invalid Int with insufficient payload",
19620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
19720f9cd88SScott Linder Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
19820f9cd88SScott Linder Current += sizeof(T);
19920f9cd88SScott Linder return true;
20020f9cd88SScott Linder }
20120f9cd88SScott Linder
readUInt(Object & Obj)20220f9cd88SScott Linder template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
20320f9cd88SScott Linder if (sizeof(T) > remainingSpace())
20420f9cd88SScott Linder return make_error<StringError>(
20520f9cd88SScott Linder "Invalid Int with insufficient payload",
20620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
20720f9cd88SScott Linder Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
20820f9cd88SScott Linder Current += sizeof(T);
20920f9cd88SScott Linder return true;
21020f9cd88SScott Linder }
21120f9cd88SScott Linder
readLength(Object & Obj)21220f9cd88SScott Linder template <class T> Expected<bool> Reader::readLength(Object &Obj) {
21320f9cd88SScott Linder if (sizeof(T) > remainingSpace())
21420f9cd88SScott Linder return make_error<StringError>(
21520f9cd88SScott Linder "Invalid Map/Array with invalid length",
21620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
21720f9cd88SScott Linder Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
21820f9cd88SScott Linder Current += sizeof(T);
21920f9cd88SScott Linder return true;
22020f9cd88SScott Linder }
22120f9cd88SScott Linder
readExt(Object & Obj)22220f9cd88SScott Linder template <class T> Expected<bool> Reader::readExt(Object &Obj) {
22320f9cd88SScott Linder if (sizeof(T) > remainingSpace())
22420f9cd88SScott Linder return make_error<StringError>(
22520f9cd88SScott Linder "Invalid Ext with invalid length",
22620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
22720f9cd88SScott Linder T Size = endian::read<T, Endianness>(Current);
22820f9cd88SScott Linder Current += sizeof(T);
22920f9cd88SScott Linder return createExt(Obj, Size);
23020f9cd88SScott Linder }
23120f9cd88SScott Linder
createRaw(Object & Obj,uint32_t Size)23220f9cd88SScott Linder Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
23320f9cd88SScott Linder if (Size > remainingSpace())
23420f9cd88SScott Linder return make_error<StringError>(
23520f9cd88SScott Linder "Invalid Raw with insufficient payload",
23620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
23720f9cd88SScott Linder Obj.Raw = StringRef(Current, Size);
23820f9cd88SScott Linder Current += Size;
23920f9cd88SScott Linder return true;
24020f9cd88SScott Linder }
24120f9cd88SScott Linder
createExt(Object & Obj,uint32_t Size)24220f9cd88SScott Linder Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
24320f9cd88SScott Linder if (Current == End)
24420f9cd88SScott Linder return make_error<StringError>(
24520f9cd88SScott Linder "Invalid Ext with no type",
24620f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
24720f9cd88SScott Linder Obj.Extension.Type = *Current++;
24820f9cd88SScott Linder if (Size > remainingSpace())
24920f9cd88SScott Linder return make_error<StringError>(
25020f9cd88SScott Linder "Invalid Ext with insufficient payload",
25120f9cd88SScott Linder std::make_error_code(std::errc::invalid_argument));
25220f9cd88SScott Linder Obj.Extension.Bytes = StringRef(Current, Size);
25320f9cd88SScott Linder Current += Size;
25420f9cd88SScott Linder return true;
25520f9cd88SScott Linder }
256