Path: blob/main/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
35232 views
//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements a MessagePack reader.10///11//===----------------------------------------------------------------------===//1213#include "llvm/BinaryFormat/MsgPackReader.h"14#include "llvm/BinaryFormat/MsgPack.h"15#include "llvm/Support/Endian.h"16#include "llvm/Support/MathExtras.h"1718using namespace llvm;19using namespace llvm::support;20using namespace msgpack;2122Reader::Reader(MemoryBufferRef InputBuffer)23: InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),24End(InputBuffer.getBufferEnd()) {}2526Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}2728Expected<bool> Reader::read(Object &Obj) {29if (Current == End)30return false;3132uint8_t FB = static_cast<uint8_t>(*Current++);3334switch (FB) {35case FirstByte::Nil:36Obj.Kind = Type::Nil;37return true;38case FirstByte::True:39Obj.Kind = Type::Boolean;40Obj.Bool = true;41return true;42case FirstByte::False:43Obj.Kind = Type::Boolean;44Obj.Bool = false;45return true;46case FirstByte::Int8:47Obj.Kind = Type::Int;48return readInt<int8_t>(Obj);49case FirstByte::Int16:50Obj.Kind = Type::Int;51return readInt<int16_t>(Obj);52case FirstByte::Int32:53Obj.Kind = Type::Int;54return readInt<int32_t>(Obj);55case FirstByte::Int64:56Obj.Kind = Type::Int;57return readInt<int64_t>(Obj);58case FirstByte::UInt8:59Obj.Kind = Type::UInt;60return readUInt<uint8_t>(Obj);61case FirstByte::UInt16:62Obj.Kind = Type::UInt;63return readUInt<uint16_t>(Obj);64case FirstByte::UInt32:65Obj.Kind = Type::UInt;66return readUInt<uint32_t>(Obj);67case FirstByte::UInt64:68Obj.Kind = Type::UInt;69return readUInt<uint64_t>(Obj);70case FirstByte::Float32:71Obj.Kind = Type::Float;72if (sizeof(float) > remainingSpace())73return make_error<StringError>(74"Invalid Float32 with insufficient payload",75std::make_error_code(std::errc::invalid_argument));76Obj.Float =77llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current));78Current += sizeof(float);79return true;80case FirstByte::Float64:81Obj.Kind = Type::Float;82if (sizeof(double) > remainingSpace())83return make_error<StringError>(84"Invalid Float64 with insufficient payload",85std::make_error_code(std::errc::invalid_argument));86Obj.Float =87llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current));88Current += sizeof(double);89return true;90case FirstByte::Str8:91Obj.Kind = Type::String;92return readRaw<uint8_t>(Obj);93case FirstByte::Str16:94Obj.Kind = Type::String;95return readRaw<uint16_t>(Obj);96case FirstByte::Str32:97Obj.Kind = Type::String;98return readRaw<uint32_t>(Obj);99case FirstByte::Bin8:100Obj.Kind = Type::Binary;101return readRaw<uint8_t>(Obj);102case FirstByte::Bin16:103Obj.Kind = Type::Binary;104return readRaw<uint16_t>(Obj);105case FirstByte::Bin32:106Obj.Kind = Type::Binary;107return readRaw<uint32_t>(Obj);108case FirstByte::Array16:109Obj.Kind = Type::Array;110return readLength<uint16_t>(Obj);111case FirstByte::Array32:112Obj.Kind = Type::Array;113return readLength<uint32_t>(Obj);114case FirstByte::Map16:115Obj.Kind = Type::Map;116return readLength<uint16_t>(Obj);117case FirstByte::Map32:118Obj.Kind = Type::Map;119return readLength<uint32_t>(Obj);120case FirstByte::FixExt1:121Obj.Kind = Type::Extension;122return createExt(Obj, FixLen::Ext1);123case FirstByte::FixExt2:124Obj.Kind = Type::Extension;125return createExt(Obj, FixLen::Ext2);126case FirstByte::FixExt4:127Obj.Kind = Type::Extension;128return createExt(Obj, FixLen::Ext4);129case FirstByte::FixExt8:130Obj.Kind = Type::Extension;131return createExt(Obj, FixLen::Ext8);132case FirstByte::FixExt16:133Obj.Kind = Type::Extension;134return createExt(Obj, FixLen::Ext16);135case FirstByte::Ext8:136Obj.Kind = Type::Extension;137return readExt<uint8_t>(Obj);138case FirstByte::Ext16:139Obj.Kind = Type::Extension;140return readExt<uint16_t>(Obj);141case FirstByte::Ext32:142Obj.Kind = Type::Extension;143return readExt<uint32_t>(Obj);144}145146if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {147Obj.Kind = Type::Int;148int8_t I;149static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");150memcpy(&I, &FB, sizeof(FB));151Obj.Int = I;152return true;153}154155if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {156Obj.Kind = Type::UInt;157Obj.UInt = FB;158return true;159}160161if ((FB & FixBitsMask::String) == FixBits::String) {162Obj.Kind = Type::String;163uint8_t Size = FB & ~FixBitsMask::String;164return createRaw(Obj, Size);165}166167if ((FB & FixBitsMask::Array) == FixBits::Array) {168Obj.Kind = Type::Array;169Obj.Length = FB & ~FixBitsMask::Array;170return true;171}172173if ((FB & FixBitsMask::Map) == FixBits::Map) {174Obj.Kind = Type::Map;175Obj.Length = FB & ~FixBitsMask::Map;176return true;177}178179return make_error<StringError>(180"Invalid first byte", std::make_error_code(std::errc::invalid_argument));181}182183template <class T> Expected<bool> Reader::readRaw(Object &Obj) {184if (sizeof(T) > remainingSpace())185return make_error<StringError>(186"Invalid Raw with insufficient payload",187std::make_error_code(std::errc::invalid_argument));188T Size = endian::read<T, Endianness>(Current);189Current += sizeof(T);190return createRaw(Obj, Size);191}192193template <class T> Expected<bool> Reader::readInt(Object &Obj) {194if (sizeof(T) > remainingSpace())195return make_error<StringError>(196"Invalid Int with insufficient payload",197std::make_error_code(std::errc::invalid_argument));198Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));199Current += sizeof(T);200return true;201}202203template <class T> Expected<bool> Reader::readUInt(Object &Obj) {204if (sizeof(T) > remainingSpace())205return make_error<StringError>(206"Invalid Int with insufficient payload",207std::make_error_code(std::errc::invalid_argument));208Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));209Current += sizeof(T);210return true;211}212213template <class T> Expected<bool> Reader::readLength(Object &Obj) {214if (sizeof(T) > remainingSpace())215return make_error<StringError>(216"Invalid Map/Array with invalid length",217std::make_error_code(std::errc::invalid_argument));218Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));219Current += sizeof(T);220return true;221}222223template <class T> Expected<bool> Reader::readExt(Object &Obj) {224if (sizeof(T) > remainingSpace())225return make_error<StringError>(226"Invalid Ext with invalid length",227std::make_error_code(std::errc::invalid_argument));228T Size = endian::read<T, Endianness>(Current);229Current += sizeof(T);230return createExt(Obj, Size);231}232233Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {234if (Size > remainingSpace())235return make_error<StringError>(236"Invalid Raw with insufficient payload",237std::make_error_code(std::errc::invalid_argument));238Obj.Raw = StringRef(Current, Size);239Current += Size;240return true;241}242243Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {244if (Current == End)245return make_error<StringError>(246"Invalid Ext with no type",247std::make_error_code(std::errc::invalid_argument));248Obj.Extension.Type = *Current++;249if (Size > remainingSpace())250return make_error<StringError>(251"Invalid Ext with insufficient payload",252std::make_error_code(std::errc::invalid_argument));253Obj.Extension.Bytes = StringRef(Current, Size);254Current += Size;255return true;256}257258259