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