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