1 //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
10 /// This file implements a MessagePack reader.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/BinaryFormat/MsgPackReader.h"
15 #include "llvm/BinaryFormat/MsgPack.h"
16 #include "llvm/Support/Endian.h"
19 using namespace llvm::support
;
20 using namespace msgpack
;
22 Reader::Reader(MemoryBufferRef InputBuffer
)
23 : InputBuffer(InputBuffer
), Current(InputBuffer
.getBufferStart()),
24 End(InputBuffer
.getBufferEnd()) {}
26 Reader::Reader(StringRef Input
) : Reader({Input
, "MsgPack"}) {}
28 Expected
<bool> Reader::read(Object
&Obj
) {
32 uint8_t FB
= static_cast<uint8_t>(*Current
++);
39 Obj
.Kind
= Type::Boolean
;
42 case FirstByte::False
:
43 Obj
.Kind
= Type::Boolean
;
48 return readInt
<int8_t>(Obj
);
49 case FirstByte::Int16
:
51 return readInt
<int16_t>(Obj
);
52 case FirstByte::Int32
:
54 return readInt
<int32_t>(Obj
);
55 case FirstByte::Int64
:
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
= BitsToFloat(endian::read
<uint32_t, Endianness
>(Current
));
77 Current
+= sizeof(float);
79 case FirstByte::Float64
:
80 Obj
.Kind
= Type::Float
;
81 if (sizeof(double) > remainingSpace())
82 return make_error
<StringError
>(
83 "Invalid Float64 with insufficient payload",
84 std::make_error_code(std::errc::invalid_argument
));
85 Obj
.Float
= BitsToDouble(endian::read
<uint64_t, Endianness
>(Current
));
86 Current
+= sizeof(double);
89 Obj
.Kind
= Type::String
;
90 return readRaw
<uint8_t>(Obj
);
91 case FirstByte::Str16
:
92 Obj
.Kind
= Type::String
;
93 return readRaw
<uint16_t>(Obj
);
94 case FirstByte::Str32
:
95 Obj
.Kind
= Type::String
;
96 return readRaw
<uint32_t>(Obj
);
98 Obj
.Kind
= Type::Binary
;
99 return readRaw
<uint8_t>(Obj
);
100 case FirstByte::Bin16
:
101 Obj
.Kind
= Type::Binary
;
102 return readRaw
<uint16_t>(Obj
);
103 case FirstByte::Bin32
:
104 Obj
.Kind
= Type::Binary
;
105 return readRaw
<uint32_t>(Obj
);
106 case FirstByte::Array16
:
107 Obj
.Kind
= Type::Array
;
108 return readLength
<uint16_t>(Obj
);
109 case FirstByte::Array32
:
110 Obj
.Kind
= Type::Array
;
111 return readLength
<uint32_t>(Obj
);
112 case FirstByte::Map16
:
113 Obj
.Kind
= Type::Map
;
114 return readLength
<uint16_t>(Obj
);
115 case FirstByte::Map32
:
116 Obj
.Kind
= Type::Map
;
117 return readLength
<uint32_t>(Obj
);
118 case FirstByte::FixExt1
:
119 Obj
.Kind
= Type::Extension
;
120 return createExt(Obj
, FixLen::Ext1
);
121 case FirstByte::FixExt2
:
122 Obj
.Kind
= Type::Extension
;
123 return createExt(Obj
, FixLen::Ext2
);
124 case FirstByte::FixExt4
:
125 Obj
.Kind
= Type::Extension
;
126 return createExt(Obj
, FixLen::Ext4
);
127 case FirstByte::FixExt8
:
128 Obj
.Kind
= Type::Extension
;
129 return createExt(Obj
, FixLen::Ext8
);
130 case FirstByte::FixExt16
:
131 Obj
.Kind
= Type::Extension
;
132 return createExt(Obj
, FixLen::Ext16
);
133 case FirstByte::Ext8
:
134 Obj
.Kind
= Type::Extension
;
135 return readExt
<uint8_t>(Obj
);
136 case FirstByte::Ext16
:
137 Obj
.Kind
= Type::Extension
;
138 return readExt
<uint16_t>(Obj
);
139 case FirstByte::Ext32
:
140 Obj
.Kind
= Type::Extension
;
141 return readExt
<uint32_t>(Obj
);
144 if ((FB
& FixBitsMask::NegativeInt
) == FixBits::NegativeInt
) {
145 Obj
.Kind
= Type::Int
;
147 static_assert(sizeof(I
) == sizeof(FB
), "Unexpected type sizes");
148 memcpy(&I
, &FB
, sizeof(FB
));
153 if ((FB
& FixBitsMask::PositiveInt
) == FixBits::PositiveInt
) {
154 Obj
.Kind
= Type::UInt
;
159 if ((FB
& FixBitsMask::String
) == FixBits::String
) {
160 Obj
.Kind
= Type::String
;
161 uint8_t Size
= FB
& ~FixBitsMask::String
;
162 return createRaw(Obj
, Size
);
165 if ((FB
& FixBitsMask::Array
) == FixBits::Array
) {
166 Obj
.Kind
= Type::Array
;
167 Obj
.Length
= FB
& ~FixBitsMask::Array
;
171 if ((FB
& FixBitsMask::Map
) == FixBits::Map
) {
172 Obj
.Kind
= Type::Map
;
173 Obj
.Length
= FB
& ~FixBitsMask::Map
;
177 return make_error
<StringError
>(
178 "Invalid first byte", std::make_error_code(std::errc::invalid_argument
));
181 template <class T
> Expected
<bool> Reader::readRaw(Object
&Obj
) {
182 if (sizeof(T
) > remainingSpace())
183 return make_error
<StringError
>(
184 "Invalid Raw with insufficient payload",
185 std::make_error_code(std::errc::invalid_argument
));
186 T Size
= endian::read
<T
, Endianness
>(Current
);
187 Current
+= sizeof(T
);
188 return createRaw(Obj
, Size
);
191 template <class T
> Expected
<bool> Reader::readInt(Object
&Obj
) {
192 if (sizeof(T
) > remainingSpace())
193 return make_error
<StringError
>(
194 "Invalid Int with insufficient payload",
195 std::make_error_code(std::errc::invalid_argument
));
196 Obj
.Int
= static_cast<int64_t>(endian::read
<T
, Endianness
>(Current
));
197 Current
+= sizeof(T
);
201 template <class T
> Expected
<bool> Reader::readUInt(Object
&Obj
) {
202 if (sizeof(T
) > remainingSpace())
203 return make_error
<StringError
>(
204 "Invalid Int with insufficient payload",
205 std::make_error_code(std::errc::invalid_argument
));
206 Obj
.UInt
= static_cast<uint64_t>(endian::read
<T
, Endianness
>(Current
));
207 Current
+= sizeof(T
);
211 template <class T
> Expected
<bool> Reader::readLength(Object
&Obj
) {
212 if (sizeof(T
) > remainingSpace())
213 return make_error
<StringError
>(
214 "Invalid Map/Array with invalid length",
215 std::make_error_code(std::errc::invalid_argument
));
216 Obj
.Length
= static_cast<size_t>(endian::read
<T
, Endianness
>(Current
));
217 Current
+= sizeof(T
);
221 template <class T
> Expected
<bool> Reader::readExt(Object
&Obj
) {
222 if (sizeof(T
) > remainingSpace())
223 return make_error
<StringError
>(
224 "Invalid Ext with invalid length",
225 std::make_error_code(std::errc::invalid_argument
));
226 T Size
= endian::read
<T
, Endianness
>(Current
);
227 Current
+= sizeof(T
);
228 return createExt(Obj
, Size
);
231 Expected
<bool> Reader::createRaw(Object
&Obj
, uint32_t Size
) {
232 if (Size
> remainingSpace())
233 return make_error
<StringError
>(
234 "Invalid Raw with insufficient payload",
235 std::make_error_code(std::errc::invalid_argument
));
236 Obj
.Raw
= StringRef(Current
, Size
);
241 Expected
<bool> Reader::createExt(Object
&Obj
, uint32_t Size
) {
243 return make_error
<StringError
>(
244 "Invalid Ext with no type",
245 std::make_error_code(std::errc::invalid_argument
));
246 Obj
.Extension
.Type
= *Current
++;
247 if (Size
> remainingSpace())
248 return make_error
<StringError
>(
249 "Invalid Ext with insufficient payload",
250 std::make_error_code(std::errc::invalid_argument
));
251 Obj
.Extension
.Bytes
= StringRef(Current
, Size
);