MsgPackReader.cpp revision 343171
1343171Sdim//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===// 2343171Sdim// 3343171Sdim// The LLVM Compiler Infrastructure 4343171Sdim// 5343171Sdim// This file is distributed under the University of Illinois Open Source 6343171Sdim// License. See LICENSE.TXT for details. 7343171Sdim// 8343171Sdim//===----------------------------------------------------------------------===// 9343171Sdim/// 10343171Sdim/// \file 11343171Sdim/// This file implements a MessagePack reader. 12343171Sdim/// 13343171Sdim//===----------------------------------------------------------------------===// 14343171Sdim 15343171Sdim#include "llvm/BinaryFormat/MsgPackReader.h" 16343171Sdim#include "llvm/BinaryFormat/MsgPack.h" 17343171Sdim#include "llvm/Support/Endian.h" 18343171Sdim 19343171Sdimusing namespace llvm; 20343171Sdimusing namespace llvm::support; 21343171Sdimusing namespace msgpack; 22343171Sdim 23343171SdimReader::Reader(MemoryBufferRef InputBuffer) 24343171Sdim : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()), 25343171Sdim End(InputBuffer.getBufferEnd()) {} 26343171Sdim 27343171SdimReader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {} 28343171Sdim 29343171SdimExpected<bool> Reader::read(Object &Obj) { 30343171Sdim if (Current == End) 31343171Sdim return false; 32343171Sdim 33343171Sdim uint8_t FB = static_cast<uint8_t>(*Current++); 34343171Sdim 35343171Sdim switch (FB) { 36343171Sdim case FirstByte::Nil: 37343171Sdim Obj.Kind = Type::Nil; 38343171Sdim return true; 39343171Sdim case FirstByte::True: 40343171Sdim Obj.Kind = Type::Boolean; 41343171Sdim Obj.Bool = true; 42343171Sdim return true; 43343171Sdim case FirstByte::False: 44343171Sdim Obj.Kind = Type::Boolean; 45343171Sdim Obj.Bool = false; 46343171Sdim return true; 47343171Sdim case FirstByte::Int8: 48343171Sdim Obj.Kind = Type::Int; 49343171Sdim return readInt<int8_t>(Obj); 50343171Sdim case FirstByte::Int16: 51343171Sdim Obj.Kind = Type::Int; 52343171Sdim return readInt<int16_t>(Obj); 53343171Sdim case FirstByte::Int32: 54343171Sdim Obj.Kind = Type::Int; 55343171Sdim return readInt<int32_t>(Obj); 56343171Sdim case FirstByte::Int64: 57343171Sdim Obj.Kind = Type::Int; 58343171Sdim return readInt<int64_t>(Obj); 59343171Sdim case FirstByte::UInt8: 60343171Sdim Obj.Kind = Type::UInt; 61343171Sdim return readUInt<uint8_t>(Obj); 62343171Sdim case FirstByte::UInt16: 63343171Sdim Obj.Kind = Type::UInt; 64343171Sdim return readUInt<uint16_t>(Obj); 65343171Sdim case FirstByte::UInt32: 66343171Sdim Obj.Kind = Type::UInt; 67343171Sdim return readUInt<uint32_t>(Obj); 68343171Sdim case FirstByte::UInt64: 69343171Sdim Obj.Kind = Type::UInt; 70343171Sdim return readUInt<uint64_t>(Obj); 71343171Sdim case FirstByte::Float32: 72343171Sdim Obj.Kind = Type::Float; 73343171Sdim if (sizeof(float) > remainingSpace()) 74343171Sdim return make_error<StringError>( 75343171Sdim "Invalid Float32 with insufficient payload", 76343171Sdim std::make_error_code(std::errc::invalid_argument)); 77343171Sdim Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current)); 78343171Sdim Current += sizeof(float); 79343171Sdim return true; 80343171Sdim case FirstByte::Float64: 81343171Sdim Obj.Kind = Type::Float; 82343171Sdim if (sizeof(double) > remainingSpace()) 83343171Sdim return make_error<StringError>( 84343171Sdim "Invalid Float64 with insufficient payload", 85343171Sdim std::make_error_code(std::errc::invalid_argument)); 86343171Sdim Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current)); 87343171Sdim Current += sizeof(double); 88343171Sdim return true; 89343171Sdim case FirstByte::Str8: 90343171Sdim Obj.Kind = Type::String; 91343171Sdim return readRaw<uint8_t>(Obj); 92343171Sdim case FirstByte::Str16: 93343171Sdim Obj.Kind = Type::String; 94343171Sdim return readRaw<uint16_t>(Obj); 95343171Sdim case FirstByte::Str32: 96343171Sdim Obj.Kind = Type::String; 97343171Sdim return readRaw<uint32_t>(Obj); 98343171Sdim case FirstByte::Bin8: 99343171Sdim Obj.Kind = Type::Binary; 100343171Sdim return readRaw<uint8_t>(Obj); 101343171Sdim case FirstByte::Bin16: 102343171Sdim Obj.Kind = Type::Binary; 103343171Sdim return readRaw<uint16_t>(Obj); 104343171Sdim case FirstByte::Bin32: 105343171Sdim Obj.Kind = Type::Binary; 106343171Sdim return readRaw<uint32_t>(Obj); 107343171Sdim case FirstByte::Array16: 108343171Sdim Obj.Kind = Type::Array; 109343171Sdim return readLength<uint16_t>(Obj); 110343171Sdim case FirstByte::Array32: 111343171Sdim Obj.Kind = Type::Array; 112343171Sdim return readLength<uint32_t>(Obj); 113343171Sdim case FirstByte::Map16: 114343171Sdim Obj.Kind = Type::Map; 115343171Sdim return readLength<uint16_t>(Obj); 116343171Sdim case FirstByte::Map32: 117343171Sdim Obj.Kind = Type::Map; 118343171Sdim return readLength<uint32_t>(Obj); 119343171Sdim case FirstByte::FixExt1: 120343171Sdim Obj.Kind = Type::Extension; 121343171Sdim return createExt(Obj, FixLen::Ext1); 122343171Sdim case FirstByte::FixExt2: 123343171Sdim Obj.Kind = Type::Extension; 124343171Sdim return createExt(Obj, FixLen::Ext2); 125343171Sdim case FirstByte::FixExt4: 126343171Sdim Obj.Kind = Type::Extension; 127343171Sdim return createExt(Obj, FixLen::Ext4); 128343171Sdim case FirstByte::FixExt8: 129343171Sdim Obj.Kind = Type::Extension; 130343171Sdim return createExt(Obj, FixLen::Ext8); 131343171Sdim case FirstByte::FixExt16: 132343171Sdim Obj.Kind = Type::Extension; 133343171Sdim return createExt(Obj, FixLen::Ext16); 134343171Sdim case FirstByte::Ext8: 135343171Sdim Obj.Kind = Type::Extension; 136343171Sdim return readExt<uint8_t>(Obj); 137343171Sdim case FirstByte::Ext16: 138343171Sdim Obj.Kind = Type::Extension; 139343171Sdim return readExt<uint16_t>(Obj); 140343171Sdim case FirstByte::Ext32: 141343171Sdim Obj.Kind = Type::Extension; 142343171Sdim return readExt<uint32_t>(Obj); 143343171Sdim } 144343171Sdim 145343171Sdim if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) { 146343171Sdim Obj.Kind = Type::Int; 147343171Sdim int8_t I; 148343171Sdim static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes"); 149343171Sdim memcpy(&I, &FB, sizeof(FB)); 150343171Sdim Obj.Int = I; 151343171Sdim return true; 152343171Sdim } 153343171Sdim 154343171Sdim if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) { 155343171Sdim Obj.Kind = Type::UInt; 156343171Sdim Obj.UInt = FB; 157343171Sdim return true; 158343171Sdim } 159343171Sdim 160343171Sdim if ((FB & FixBitsMask::String) == FixBits::String) { 161343171Sdim Obj.Kind = Type::String; 162343171Sdim uint8_t Size = FB & ~FixBitsMask::String; 163343171Sdim return createRaw(Obj, Size); 164343171Sdim } 165343171Sdim 166343171Sdim if ((FB & FixBitsMask::Array) == FixBits::Array) { 167343171Sdim Obj.Kind = Type::Array; 168343171Sdim Obj.Length = FB & ~FixBitsMask::Array; 169343171Sdim return true; 170343171Sdim } 171343171Sdim 172343171Sdim if ((FB & FixBitsMask::Map) == FixBits::Map) { 173343171Sdim Obj.Kind = Type::Map; 174343171Sdim Obj.Length = FB & ~FixBitsMask::Map; 175343171Sdim return true; 176343171Sdim } 177343171Sdim 178343171Sdim return make_error<StringError>( 179343171Sdim "Invalid first byte", std::make_error_code(std::errc::invalid_argument)); 180343171Sdim} 181343171Sdim 182343171Sdimtemplate <class T> Expected<bool> Reader::readRaw(Object &Obj) { 183343171Sdim if (sizeof(T) > remainingSpace()) 184343171Sdim return make_error<StringError>( 185343171Sdim "Invalid Raw with insufficient payload", 186343171Sdim std::make_error_code(std::errc::invalid_argument)); 187343171Sdim T Size = endian::read<T, Endianness>(Current); 188343171Sdim Current += sizeof(T); 189343171Sdim return createRaw(Obj, Size); 190343171Sdim} 191343171Sdim 192343171Sdimtemplate <class T> Expected<bool> Reader::readInt(Object &Obj) { 193343171Sdim if (sizeof(T) > remainingSpace()) 194343171Sdim return make_error<StringError>( 195343171Sdim "Invalid Int with insufficient payload", 196343171Sdim std::make_error_code(std::errc::invalid_argument)); 197343171Sdim Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current)); 198343171Sdim Current += sizeof(T); 199343171Sdim return true; 200343171Sdim} 201343171Sdim 202343171Sdimtemplate <class T> Expected<bool> Reader::readUInt(Object &Obj) { 203343171Sdim if (sizeof(T) > remainingSpace()) 204343171Sdim return make_error<StringError>( 205343171Sdim "Invalid Int with insufficient payload", 206343171Sdim std::make_error_code(std::errc::invalid_argument)); 207343171Sdim Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current)); 208343171Sdim Current += sizeof(T); 209343171Sdim return true; 210343171Sdim} 211343171Sdim 212343171Sdimtemplate <class T> Expected<bool> Reader::readLength(Object &Obj) { 213343171Sdim if (sizeof(T) > remainingSpace()) 214343171Sdim return make_error<StringError>( 215343171Sdim "Invalid Map/Array with invalid length", 216343171Sdim std::make_error_code(std::errc::invalid_argument)); 217343171Sdim Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current)); 218343171Sdim Current += sizeof(T); 219343171Sdim return true; 220343171Sdim} 221343171Sdim 222343171Sdimtemplate <class T> Expected<bool> Reader::readExt(Object &Obj) { 223343171Sdim if (sizeof(T) > remainingSpace()) 224343171Sdim return make_error<StringError>( 225343171Sdim "Invalid Ext with invalid length", 226343171Sdim std::make_error_code(std::errc::invalid_argument)); 227343171Sdim T Size = endian::read<T, Endianness>(Current); 228343171Sdim Current += sizeof(T); 229343171Sdim return createExt(Obj, Size); 230343171Sdim} 231343171Sdim 232343171SdimExpected<bool> Reader::createRaw(Object &Obj, uint32_t Size) { 233343171Sdim if (Size > remainingSpace()) 234343171Sdim return make_error<StringError>( 235343171Sdim "Invalid Raw with insufficient payload", 236343171Sdim std::make_error_code(std::errc::invalid_argument)); 237343171Sdim Obj.Raw = StringRef(Current, Size); 238343171Sdim Current += Size; 239343171Sdim return true; 240343171Sdim} 241343171Sdim 242343171SdimExpected<bool> Reader::createExt(Object &Obj, uint32_t Size) { 243343171Sdim if (Current == End) 244343171Sdim return make_error<StringError>( 245343171Sdim "Invalid Ext with no type", 246343171Sdim std::make_error_code(std::errc::invalid_argument)); 247343171Sdim Obj.Extension.Type = *Current++; 248343171Sdim if (Size > remainingSpace()) 249343171Sdim return make_error<StringError>( 250343171Sdim "Invalid Ext with insufficient payload", 251343171Sdim std::make_error_code(std::errc::invalid_argument)); 252343171Sdim Obj.Extension.Bytes = StringRef(Current, Size); 253343171Sdim Current += Size; 254343171Sdim return true; 255343171Sdim} 256