123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// This file implements a MessagePack reader.
- ///
- //===----------------------------------------------------------------------===//
- #include "llvm/BinaryFormat/MsgPackReader.h"
- #include "llvm/BinaryFormat/MsgPack.h"
- #include "llvm/Support/Endian.h"
- #include "llvm/Support/MathExtras.h"
- using namespace llvm;
- using namespace llvm::support;
- using namespace msgpack;
- Reader::Reader(MemoryBufferRef InputBuffer)
- : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
- End(InputBuffer.getBufferEnd()) {}
- Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
- Expected<bool> Reader::read(Object &Obj) {
- if (Current == End)
- return false;
- uint8_t FB = static_cast<uint8_t>(*Current++);
- switch (FB) {
- case FirstByte::Nil:
- Obj.Kind = Type::Nil;
- return true;
- case FirstByte::True:
- Obj.Kind = Type::Boolean;
- Obj.Bool = true;
- return true;
- case FirstByte::False:
- Obj.Kind = Type::Boolean;
- Obj.Bool = false;
- return true;
- case FirstByte::Int8:
- Obj.Kind = Type::Int;
- return readInt<int8_t>(Obj);
- case FirstByte::Int16:
- Obj.Kind = Type::Int;
- return readInt<int16_t>(Obj);
- case FirstByte::Int32:
- Obj.Kind = Type::Int;
- return readInt<int32_t>(Obj);
- case FirstByte::Int64:
- Obj.Kind = Type::Int;
- return readInt<int64_t>(Obj);
- case FirstByte::UInt8:
- Obj.Kind = Type::UInt;
- return readUInt<uint8_t>(Obj);
- case FirstByte::UInt16:
- Obj.Kind = Type::UInt;
- return readUInt<uint16_t>(Obj);
- case FirstByte::UInt32:
- Obj.Kind = Type::UInt;
- return readUInt<uint32_t>(Obj);
- case FirstByte::UInt64:
- Obj.Kind = Type::UInt;
- return readUInt<uint64_t>(Obj);
- case FirstByte::Float32:
- Obj.Kind = Type::Float;
- if (sizeof(float) > remainingSpace())
- return make_error<StringError>(
- "Invalid Float32 with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
- Current += sizeof(float);
- return true;
- case FirstByte::Float64:
- Obj.Kind = Type::Float;
- if (sizeof(double) > remainingSpace())
- return make_error<StringError>(
- "Invalid Float64 with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
- Current += sizeof(double);
- return true;
- case FirstByte::Str8:
- Obj.Kind = Type::String;
- return readRaw<uint8_t>(Obj);
- case FirstByte::Str16:
- Obj.Kind = Type::String;
- return readRaw<uint16_t>(Obj);
- case FirstByte::Str32:
- Obj.Kind = Type::String;
- return readRaw<uint32_t>(Obj);
- case FirstByte::Bin8:
- Obj.Kind = Type::Binary;
- return readRaw<uint8_t>(Obj);
- case FirstByte::Bin16:
- Obj.Kind = Type::Binary;
- return readRaw<uint16_t>(Obj);
- case FirstByte::Bin32:
- Obj.Kind = Type::Binary;
- return readRaw<uint32_t>(Obj);
- case FirstByte::Array16:
- Obj.Kind = Type::Array;
- return readLength<uint16_t>(Obj);
- case FirstByte::Array32:
- Obj.Kind = Type::Array;
- return readLength<uint32_t>(Obj);
- case FirstByte::Map16:
- Obj.Kind = Type::Map;
- return readLength<uint16_t>(Obj);
- case FirstByte::Map32:
- Obj.Kind = Type::Map;
- return readLength<uint32_t>(Obj);
- case FirstByte::FixExt1:
- Obj.Kind = Type::Extension;
- return createExt(Obj, FixLen::Ext1);
- case FirstByte::FixExt2:
- Obj.Kind = Type::Extension;
- return createExt(Obj, FixLen::Ext2);
- case FirstByte::FixExt4:
- Obj.Kind = Type::Extension;
- return createExt(Obj, FixLen::Ext4);
- case FirstByte::FixExt8:
- Obj.Kind = Type::Extension;
- return createExt(Obj, FixLen::Ext8);
- case FirstByte::FixExt16:
- Obj.Kind = Type::Extension;
- return createExt(Obj, FixLen::Ext16);
- case FirstByte::Ext8:
- Obj.Kind = Type::Extension;
- return readExt<uint8_t>(Obj);
- case FirstByte::Ext16:
- Obj.Kind = Type::Extension;
- return readExt<uint16_t>(Obj);
- case FirstByte::Ext32:
- Obj.Kind = Type::Extension;
- return readExt<uint32_t>(Obj);
- }
- if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
- Obj.Kind = Type::Int;
- int8_t I;
- static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
- memcpy(&I, &FB, sizeof(FB));
- Obj.Int = I;
- return true;
- }
- if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
- Obj.Kind = Type::UInt;
- Obj.UInt = FB;
- return true;
- }
- if ((FB & FixBitsMask::String) == FixBits::String) {
- Obj.Kind = Type::String;
- uint8_t Size = FB & ~FixBitsMask::String;
- return createRaw(Obj, Size);
- }
- if ((FB & FixBitsMask::Array) == FixBits::Array) {
- Obj.Kind = Type::Array;
- Obj.Length = FB & ~FixBitsMask::Array;
- return true;
- }
- if ((FB & FixBitsMask::Map) == FixBits::Map) {
- Obj.Kind = Type::Map;
- Obj.Length = FB & ~FixBitsMask::Map;
- return true;
- }
- return make_error<StringError>(
- "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
- }
- template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
- if (sizeof(T) > remainingSpace())
- return make_error<StringError>(
- "Invalid Raw with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- T Size = endian::read<T, Endianness>(Current);
- Current += sizeof(T);
- return createRaw(Obj, Size);
- }
- template <class T> Expected<bool> Reader::readInt(Object &Obj) {
- if (sizeof(T) > remainingSpace())
- return make_error<StringError>(
- "Invalid Int with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
- Current += sizeof(T);
- return true;
- }
- template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
- if (sizeof(T) > remainingSpace())
- return make_error<StringError>(
- "Invalid Int with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
- Current += sizeof(T);
- return true;
- }
- template <class T> Expected<bool> Reader::readLength(Object &Obj) {
- if (sizeof(T) > remainingSpace())
- return make_error<StringError>(
- "Invalid Map/Array with invalid length",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
- Current += sizeof(T);
- return true;
- }
- template <class T> Expected<bool> Reader::readExt(Object &Obj) {
- if (sizeof(T) > remainingSpace())
- return make_error<StringError>(
- "Invalid Ext with invalid length",
- std::make_error_code(std::errc::invalid_argument));
- T Size = endian::read<T, Endianness>(Current);
- Current += sizeof(T);
- return createExt(Obj, Size);
- }
- Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
- if (Size > remainingSpace())
- return make_error<StringError>(
- "Invalid Raw with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Raw = StringRef(Current, Size);
- Current += Size;
- return true;
- }
- Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
- if (Current == End)
- return make_error<StringError>(
- "Invalid Ext with no type",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Extension.Type = *Current++;
- if (Size > remainingSpace())
- return make_error<StringError>(
- "Invalid Ext with insufficient payload",
- std::make_error_code(std::errc::invalid_argument));
- Obj.Extension.Bytes = StringRef(Current, Size);
- Current += Size;
- return true;
- }
|