1 //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements a MessagePack reader.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/BinaryFormat/MsgPackReader.h"
16 #include "llvm/BinaryFormat/MsgPack.h"
17 #include "llvm/Support/Endian.h"
20 using namespace llvm::support
;
21 using namespace msgpack
;
23 Reader::Reader(MemoryBufferRef InputBuffer
)
24 : InputBuffer(InputBuffer
), Current(InputBuffer
.getBufferStart()),
25 End(InputBuffer
.getBufferEnd()) {}
27 Reader::Reader(StringRef Input
) : Reader({Input
, "MsgPack"}) {}
29 Expected
<bool> Reader::read(Object
&Obj
) {
33 uint8_t FB
= static_cast<uint8_t>(*Current
++);
40 Obj
.Kind
= Type::Boolean
;
43 case FirstByte::False
:
44 Obj
.Kind
= Type::Boolean
;
49 return readInt
<int8_t>(Obj
);
50 case FirstByte::Int16
:
52 return readInt
<int16_t>(Obj
);
53 case FirstByte::Int32
:
55 return readInt
<int32_t>(Obj
);
56 case FirstByte::Int64
:
58 return readInt
<int64_t>(Obj
);
59 case FirstByte::UInt8
:
60 Obj
.Kind
= Type::UInt
;
61 return readUInt
<uint8_t>(Obj
);
62 case FirstByte::UInt16
:
63 Obj
.Kind
= Type::UInt
;
64 return readUInt
<uint16_t>(Obj
);
65 case FirstByte::UInt32
:
66 Obj
.Kind
= Type::UInt
;
67 return readUInt
<uint32_t>(Obj
);
68 case FirstByte::UInt64
:
69 Obj
.Kind
= Type::UInt
;
70 return readUInt
<uint64_t>(Obj
);
71 case FirstByte::Float32
:
72 Obj
.Kind
= Type::Float
;
73 if (sizeof(float) > remainingSpace())
74 return make_error
<StringError
>(
75 "Invalid Float32 with insufficient payload",
76 std::make_error_code(std::errc::invalid_argument
));
77 Obj
.Float
= BitsToFloat(endian::read
<uint32_t, Endianness
>(Current
));
78 Current
+= sizeof(float);
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
= BitsToDouble(endian::read
<uint64_t, Endianness
>(Current
));
87 Current
+= sizeof(double);
90 Obj
.Kind
= Type::String
;
91 return readRaw
<uint8_t>(Obj
);
92 case FirstByte::Str16
:
93 Obj
.Kind
= Type::String
;
94 return readRaw
<uint16_t>(Obj
);
95 case FirstByte::Str32
:
96 Obj
.Kind
= Type::String
;
97 return readRaw
<uint32_t>(Obj
);
99 Obj
.Kind
= Type::Binary
;
100 return readRaw
<uint8_t>(Obj
);
101 case FirstByte::Bin16
:
102 Obj
.Kind
= Type::Binary
;
103 return readRaw
<uint16_t>(Obj
);
104 case FirstByte::Bin32
:
105 Obj
.Kind
= Type::Binary
;
106 return readRaw
<uint32_t>(Obj
);
107 case FirstByte::Array16
:
108 Obj
.Kind
= Type::Array
;
109 return readLength
<uint16_t>(Obj
);
110 case FirstByte::Array32
:
111 Obj
.Kind
= Type::Array
;
112 return readLength
<uint32_t>(Obj
);
113 case FirstByte::Map16
:
114 Obj
.Kind
= Type::Map
;
115 return readLength
<uint16_t>(Obj
);
116 case FirstByte::Map32
:
117 Obj
.Kind
= Type::Map
;
118 return readLength
<uint32_t>(Obj
);
119 case FirstByte::FixExt1
:
120 Obj
.Kind
= Type::Extension
;
121 return createExt(Obj
, FixLen::Ext1
);
122 case FirstByte::FixExt2
:
123 Obj
.Kind
= Type::Extension
;
124 return createExt(Obj
, FixLen::Ext2
);
125 case FirstByte::FixExt4
:
126 Obj
.Kind
= Type::Extension
;
127 return createExt(Obj
, FixLen::Ext4
);
128 case FirstByte::FixExt8
:
129 Obj
.Kind
= Type::Extension
;
130 return createExt(Obj
, FixLen::Ext8
);
131 case FirstByte::FixExt16
:
132 Obj
.Kind
= Type::Extension
;
133 return createExt(Obj
, FixLen::Ext16
);
134 case FirstByte::Ext8
:
135 Obj
.Kind
= Type::Extension
;
136 return readExt
<uint8_t>(Obj
);
137 case FirstByte::Ext16
:
138 Obj
.Kind
= Type::Extension
;
139 return readExt
<uint16_t>(Obj
);
140 case FirstByte::Ext32
:
141 Obj
.Kind
= Type::Extension
;
142 return readExt
<uint32_t>(Obj
);
145 if ((FB
& FixBitsMask::NegativeInt
) == FixBits::NegativeInt
) {
146 Obj
.Kind
= Type::Int
;
148 static_assert(sizeof(I
) == sizeof(FB
), "Unexpected type sizes");
149 memcpy(&I
, &FB
, sizeof(FB
));
154 if ((FB
& FixBitsMask::PositiveInt
) == FixBits::PositiveInt
) {
155 Obj
.Kind
= Type::UInt
;
160 if ((FB
& FixBitsMask::String
) == FixBits::String
) {
161 Obj
.Kind
= Type::String
;
162 uint8_t Size
= FB
& ~FixBitsMask::String
;
163 return createRaw(Obj
, Size
);
166 if ((FB
& FixBitsMask::Array
) == FixBits::Array
) {
167 Obj
.Kind
= Type::Array
;
168 Obj
.Length
= FB
& ~FixBitsMask::Array
;
172 if ((FB
& FixBitsMask::Map
) == FixBits::Map
) {
173 Obj
.Kind
= Type::Map
;
174 Obj
.Length
= FB
& ~FixBitsMask::Map
;
178 return make_error
<StringError
>(
179 "Invalid first byte", std::make_error_code(std::errc::invalid_argument
));
182 template <class T
> Expected
<bool> Reader::readRaw(Object
&Obj
) {
183 if (sizeof(T
) > remainingSpace())
184 return make_error
<StringError
>(
185 "Invalid Raw with insufficient payload",
186 std::make_error_code(std::errc::invalid_argument
));
187 T Size
= endian::read
<T
, Endianness
>(Current
);
188 Current
+= sizeof(T
);
189 return createRaw(Obj
, Size
);
192 template <class T
> Expected
<bool> Reader::readInt(Object
&Obj
) {
193 if (sizeof(T
) > remainingSpace())
194 return make_error
<StringError
>(
195 "Invalid Int with insufficient payload",
196 std::make_error_code(std::errc::invalid_argument
));
197 Obj
.Int
= static_cast<int64_t>(endian::read
<T
, Endianness
>(Current
));
198 Current
+= sizeof(T
);
202 template <class T
> Expected
<bool> Reader::readUInt(Object
&Obj
) {
203 if (sizeof(T
) > remainingSpace())
204 return make_error
<StringError
>(
205 "Invalid Int with insufficient payload",
206 std::make_error_code(std::errc::invalid_argument
));
207 Obj
.UInt
= static_cast<uint64_t>(endian::read
<T
, Endianness
>(Current
));
208 Current
+= sizeof(T
);
212 template <class T
> Expected
<bool> Reader::readLength(Object
&Obj
) {
213 if (sizeof(T
) > remainingSpace())
214 return make_error
<StringError
>(
215 "Invalid Map/Array with invalid length",
216 std::make_error_code(std::errc::invalid_argument
));
217 Obj
.Length
= static_cast<size_t>(endian::read
<T
, Endianness
>(Current
));
218 Current
+= sizeof(T
);
222 template <class T
> Expected
<bool> Reader::readExt(Object
&Obj
) {
223 if (sizeof(T
) > remainingSpace())
224 return make_error
<StringError
>(
225 "Invalid Ext with invalid length",
226 std::make_error_code(std::errc::invalid_argument
));
227 T Size
= endian::read
<T
, Endianness
>(Current
);
228 Current
+= sizeof(T
);
229 return createExt(Obj
, Size
);
232 Expected
<bool> Reader::createRaw(Object
&Obj
, uint32_t Size
) {
233 if (Size
> remainingSpace())
234 return make_error
<StringError
>(
235 "Invalid Raw with insufficient payload",
236 std::make_error_code(std::errc::invalid_argument
));
237 Obj
.Raw
= StringRef(Current
, Size
);
242 Expected
<bool> Reader::createExt(Object
&Obj
, uint32_t Size
) {
244 return make_error
<StringError
>(
245 "Invalid Ext with no type",
246 std::make_error_code(std::errc::invalid_argument
));
247 Obj
.Extension
.Type
= *Current
++;
248 if (Size
> remainingSpace())
249 return make_error
<StringError
>(
250 "Invalid Ext with insufficient payload",
251 std::make_error_code(std::errc::invalid_argument
));
252 Obj
.Extension
.Bytes
= StringRef(Current
, Size
);