xref: /llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp (revision 64dad4ba9af603330458a7673e39a873afdf3d4d)
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"
1724b9bc84SSimon 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));
77*64dad4baSKazu Hirata     Obj.Float =
78*64dad4baSKazu Hirata         llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current));
7920f9cd88SScott Linder     Current += sizeof(float);
8020f9cd88SScott Linder     return true;
8120f9cd88SScott Linder   case FirstByte::Float64:
8220f9cd88SScott Linder     Obj.Kind = Type::Float;
8320f9cd88SScott Linder     if (sizeof(double) > remainingSpace())
8420f9cd88SScott Linder       return make_error<StringError>(
8520f9cd88SScott Linder           "Invalid Float64 with insufficient payload",
8620f9cd88SScott Linder           std::make_error_code(std::errc::invalid_argument));
87*64dad4baSKazu Hirata     Obj.Float =
88*64dad4baSKazu Hirata         llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current));
8920f9cd88SScott Linder     Current += sizeof(double);
9020f9cd88SScott Linder     return true;
9120f9cd88SScott Linder   case FirstByte::Str8:
9220f9cd88SScott Linder     Obj.Kind = Type::String;
9320f9cd88SScott Linder     return readRaw<uint8_t>(Obj);
9420f9cd88SScott Linder   case FirstByte::Str16:
9520f9cd88SScott Linder     Obj.Kind = Type::String;
9620f9cd88SScott Linder     return readRaw<uint16_t>(Obj);
9720f9cd88SScott Linder   case FirstByte::Str32:
9820f9cd88SScott Linder     Obj.Kind = Type::String;
9920f9cd88SScott Linder     return readRaw<uint32_t>(Obj);
10020f9cd88SScott Linder   case FirstByte::Bin8:
10120f9cd88SScott Linder     Obj.Kind = Type::Binary;
10220f9cd88SScott Linder     return readRaw<uint8_t>(Obj);
10320f9cd88SScott Linder   case FirstByte::Bin16:
10420f9cd88SScott Linder     Obj.Kind = Type::Binary;
10520f9cd88SScott Linder     return readRaw<uint16_t>(Obj);
10620f9cd88SScott Linder   case FirstByte::Bin32:
10720f9cd88SScott Linder     Obj.Kind = Type::Binary;
10820f9cd88SScott Linder     return readRaw<uint32_t>(Obj);
10920f9cd88SScott Linder   case FirstByte::Array16:
11020f9cd88SScott Linder     Obj.Kind = Type::Array;
11120f9cd88SScott Linder     return readLength<uint16_t>(Obj);
11220f9cd88SScott Linder   case FirstByte::Array32:
11320f9cd88SScott Linder     Obj.Kind = Type::Array;
11420f9cd88SScott Linder     return readLength<uint32_t>(Obj);
11520f9cd88SScott Linder   case FirstByte::Map16:
11620f9cd88SScott Linder     Obj.Kind = Type::Map;
11720f9cd88SScott Linder     return readLength<uint16_t>(Obj);
11820f9cd88SScott Linder   case FirstByte::Map32:
11920f9cd88SScott Linder     Obj.Kind = Type::Map;
12020f9cd88SScott Linder     return readLength<uint32_t>(Obj);
12120f9cd88SScott Linder   case FirstByte::FixExt1:
12220f9cd88SScott Linder     Obj.Kind = Type::Extension;
12320f9cd88SScott Linder     return createExt(Obj, FixLen::Ext1);
12420f9cd88SScott Linder   case FirstByte::FixExt2:
12520f9cd88SScott Linder     Obj.Kind = Type::Extension;
12620f9cd88SScott Linder     return createExt(Obj, FixLen::Ext2);
12720f9cd88SScott Linder   case FirstByte::FixExt4:
12820f9cd88SScott Linder     Obj.Kind = Type::Extension;
12920f9cd88SScott Linder     return createExt(Obj, FixLen::Ext4);
13020f9cd88SScott Linder   case FirstByte::FixExt8:
13120f9cd88SScott Linder     Obj.Kind = Type::Extension;
13220f9cd88SScott Linder     return createExt(Obj, FixLen::Ext8);
13320f9cd88SScott Linder   case FirstByte::FixExt16:
13420f9cd88SScott Linder     Obj.Kind = Type::Extension;
13520f9cd88SScott Linder     return createExt(Obj, FixLen::Ext16);
13620f9cd88SScott Linder   case FirstByte::Ext8:
13720f9cd88SScott Linder     Obj.Kind = Type::Extension;
13820f9cd88SScott Linder     return readExt<uint8_t>(Obj);
13920f9cd88SScott Linder   case FirstByte::Ext16:
14020f9cd88SScott Linder     Obj.Kind = Type::Extension;
14120f9cd88SScott Linder     return readExt<uint16_t>(Obj);
14220f9cd88SScott Linder   case FirstByte::Ext32:
14320f9cd88SScott Linder     Obj.Kind = Type::Extension;
14420f9cd88SScott Linder     return readExt<uint32_t>(Obj);
14520f9cd88SScott Linder   }
14620f9cd88SScott Linder 
14720f9cd88SScott Linder   if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
14820f9cd88SScott Linder     Obj.Kind = Type::Int;
14920f9cd88SScott Linder     int8_t I;
15020f9cd88SScott Linder     static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
15120f9cd88SScott Linder     memcpy(&I, &FB, sizeof(FB));
15220f9cd88SScott Linder     Obj.Int = I;
15320f9cd88SScott Linder     return true;
15420f9cd88SScott Linder   }
15520f9cd88SScott Linder 
15620f9cd88SScott Linder   if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
15720f9cd88SScott Linder     Obj.Kind = Type::UInt;
15820f9cd88SScott Linder     Obj.UInt = FB;
15920f9cd88SScott Linder     return true;
16020f9cd88SScott Linder   }
16120f9cd88SScott Linder 
16220f9cd88SScott Linder   if ((FB & FixBitsMask::String) == FixBits::String) {
16320f9cd88SScott Linder     Obj.Kind = Type::String;
16420f9cd88SScott Linder     uint8_t Size = FB & ~FixBitsMask::String;
16520f9cd88SScott Linder     return createRaw(Obj, Size);
16620f9cd88SScott Linder   }
16720f9cd88SScott Linder 
16820f9cd88SScott Linder   if ((FB & FixBitsMask::Array) == FixBits::Array) {
16920f9cd88SScott Linder     Obj.Kind = Type::Array;
17020f9cd88SScott Linder     Obj.Length = FB & ~FixBitsMask::Array;
17120f9cd88SScott Linder     return true;
17220f9cd88SScott Linder   }
17320f9cd88SScott Linder 
17420f9cd88SScott Linder   if ((FB & FixBitsMask::Map) == FixBits::Map) {
17520f9cd88SScott Linder     Obj.Kind = Type::Map;
17620f9cd88SScott Linder     Obj.Length = FB & ~FixBitsMask::Map;
17720f9cd88SScott Linder     return true;
17820f9cd88SScott Linder   }
17920f9cd88SScott Linder 
18020f9cd88SScott Linder   return make_error<StringError>(
18120f9cd88SScott Linder       "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
18220f9cd88SScott Linder }
18320f9cd88SScott Linder 
readRaw(Object & Obj)18420f9cd88SScott Linder template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
18520f9cd88SScott Linder   if (sizeof(T) > remainingSpace())
18620f9cd88SScott Linder     return make_error<StringError>(
18720f9cd88SScott Linder         "Invalid Raw with insufficient payload",
18820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
18920f9cd88SScott Linder   T Size = endian::read<T, Endianness>(Current);
19020f9cd88SScott Linder   Current += sizeof(T);
19120f9cd88SScott Linder   return createRaw(Obj, Size);
19220f9cd88SScott Linder }
19320f9cd88SScott Linder 
readInt(Object & Obj)19420f9cd88SScott Linder template <class T> Expected<bool> Reader::readInt(Object &Obj) {
19520f9cd88SScott Linder   if (sizeof(T) > remainingSpace())
19620f9cd88SScott Linder     return make_error<StringError>(
19720f9cd88SScott Linder         "Invalid Int with insufficient payload",
19820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
19920f9cd88SScott Linder   Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
20020f9cd88SScott Linder   Current += sizeof(T);
20120f9cd88SScott Linder   return true;
20220f9cd88SScott Linder }
20320f9cd88SScott Linder 
readUInt(Object & Obj)20420f9cd88SScott Linder template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
20520f9cd88SScott Linder   if (sizeof(T) > remainingSpace())
20620f9cd88SScott Linder     return make_error<StringError>(
20720f9cd88SScott Linder         "Invalid Int with insufficient payload",
20820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
20920f9cd88SScott Linder   Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
21020f9cd88SScott Linder   Current += sizeof(T);
21120f9cd88SScott Linder   return true;
21220f9cd88SScott Linder }
21320f9cd88SScott Linder 
readLength(Object & Obj)21420f9cd88SScott Linder template <class T> Expected<bool> Reader::readLength(Object &Obj) {
21520f9cd88SScott Linder   if (sizeof(T) > remainingSpace())
21620f9cd88SScott Linder     return make_error<StringError>(
21720f9cd88SScott Linder         "Invalid Map/Array with invalid length",
21820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
21920f9cd88SScott Linder   Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
22020f9cd88SScott Linder   Current += sizeof(T);
22120f9cd88SScott Linder   return true;
22220f9cd88SScott Linder }
22320f9cd88SScott Linder 
readExt(Object & Obj)22420f9cd88SScott Linder template <class T> Expected<bool> Reader::readExt(Object &Obj) {
22520f9cd88SScott Linder   if (sizeof(T) > remainingSpace())
22620f9cd88SScott Linder     return make_error<StringError>(
22720f9cd88SScott Linder         "Invalid Ext with invalid length",
22820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
22920f9cd88SScott Linder   T Size = endian::read<T, Endianness>(Current);
23020f9cd88SScott Linder   Current += sizeof(T);
23120f9cd88SScott Linder   return createExt(Obj, Size);
23220f9cd88SScott Linder }
23320f9cd88SScott Linder 
createRaw(Object & Obj,uint32_t Size)23420f9cd88SScott Linder Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
23520f9cd88SScott Linder   if (Size > remainingSpace())
23620f9cd88SScott Linder     return make_error<StringError>(
23720f9cd88SScott Linder         "Invalid Raw with insufficient payload",
23820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
23920f9cd88SScott Linder   Obj.Raw = StringRef(Current, Size);
24020f9cd88SScott Linder   Current += Size;
24120f9cd88SScott Linder   return true;
24220f9cd88SScott Linder }
24320f9cd88SScott Linder 
createExt(Object & Obj,uint32_t Size)24420f9cd88SScott Linder Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
24520f9cd88SScott Linder   if (Current == End)
24620f9cd88SScott Linder     return make_error<StringError>(
24720f9cd88SScott Linder         "Invalid Ext with no type",
24820f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
24920f9cd88SScott Linder   Obj.Extension.Type = *Current++;
25020f9cd88SScott Linder   if (Size > remainingSpace())
25120f9cd88SScott Linder     return make_error<StringError>(
25220f9cd88SScott Linder         "Invalid Ext with insufficient payload",
25320f9cd88SScott Linder         std::make_error_code(std::errc::invalid_argument));
25420f9cd88SScott Linder   Obj.Extension.Bytes = StringRef(Current, Size);
25520f9cd88SScott Linder   Current += Size;
25620f9cd88SScott Linder   return true;
25720f9cd88SScott Linder }
258