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"
17 #include "llvm/Support/MathExtras.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
));
78 llvm::bit_cast
<float>(endian::read
<uint32_t, Endianness
>(Current
));
79 Current
+= sizeof(float);
81 case FirstByte::Float64
:
82 Obj
.Kind
= Type::Float
;
83 if (sizeof(double) > remainingSpace())
84 return make_error
<StringError
>(
85 "Invalid Float64 with insufficient payload",
86 std::make_error_code(std::errc::invalid_argument
));
88 llvm::bit_cast
<double>(endian::read
<uint64_t, Endianness
>(Current
));
89 Current
+= sizeof(double);
92 Obj
.Kind
= Type::String
;
93 return readRaw
<uint8_t>(Obj
);
94 case FirstByte::Str16
:
95 Obj
.Kind
= Type::String
;
96 return readRaw
<uint16_t>(Obj
);
97 case FirstByte::Str32
:
98 Obj
.Kind
= Type::String
;
99 return readRaw
<uint32_t>(Obj
);
100 case FirstByte::Bin8
:
101 Obj
.Kind
= Type::Binary
;
102 return readRaw
<uint8_t>(Obj
);
103 case FirstByte::Bin16
:
104 Obj
.Kind
= Type::Binary
;
105 return readRaw
<uint16_t>(Obj
);
106 case FirstByte::Bin32
:
107 Obj
.Kind
= Type::Binary
;
108 return readRaw
<uint32_t>(Obj
);
109 case FirstByte::Array16
:
110 Obj
.Kind
= Type::Array
;
111 return readLength
<uint16_t>(Obj
);
112 case FirstByte::Array32
:
113 Obj
.Kind
= Type::Array
;
114 return readLength
<uint32_t>(Obj
);
115 case FirstByte::Map16
:
116 Obj
.Kind
= Type::Map
;
117 return readLength
<uint16_t>(Obj
);
118 case FirstByte::Map32
:
119 Obj
.Kind
= Type::Map
;
120 return readLength
<uint32_t>(Obj
);
121 case FirstByte::FixExt1
:
122 Obj
.Kind
= Type::Extension
;
123 return createExt(Obj
, FixLen::Ext1
);
124 case FirstByte::FixExt2
:
125 Obj
.Kind
= Type::Extension
;
126 return createExt(Obj
, FixLen::Ext2
);
127 case FirstByte::FixExt4
:
128 Obj
.Kind
= Type::Extension
;
129 return createExt(Obj
, FixLen::Ext4
);
130 case FirstByte::FixExt8
:
131 Obj
.Kind
= Type::Extension
;
132 return createExt(Obj
, FixLen::Ext8
);
133 case FirstByte::FixExt16
:
134 Obj
.Kind
= Type::Extension
;
135 return createExt(Obj
, FixLen::Ext16
);
136 case FirstByte::Ext8
:
137 Obj
.Kind
= Type::Extension
;
138 return readExt
<uint8_t>(Obj
);
139 case FirstByte::Ext16
:
140 Obj
.Kind
= Type::Extension
;
141 return readExt
<uint16_t>(Obj
);
142 case FirstByte::Ext32
:
143 Obj
.Kind
= Type::Extension
;
144 return readExt
<uint32_t>(Obj
);
147 if ((FB
& FixBitsMask::NegativeInt
) == FixBits::NegativeInt
) {
148 Obj
.Kind
= Type::Int
;
150 static_assert(sizeof(I
) == sizeof(FB
), "Unexpected type sizes");
151 memcpy(&I
, &FB
, sizeof(FB
));
156 if ((FB
& FixBitsMask::PositiveInt
) == FixBits::PositiveInt
) {
157 Obj
.Kind
= Type::UInt
;
162 if ((FB
& FixBitsMask::String
) == FixBits::String
) {
163 Obj
.Kind
= Type::String
;
164 uint8_t Size
= FB
& ~FixBitsMask::String
;
165 return createRaw(Obj
, Size
);
168 if ((FB
& FixBitsMask::Array
) == FixBits::Array
) {
169 Obj
.Kind
= Type::Array
;
170 Obj
.Length
= FB
& ~FixBitsMask::Array
;
174 if ((FB
& FixBitsMask::Map
) == FixBits::Map
) {
175 Obj
.Kind
= Type::Map
;
176 Obj
.Length
= FB
& ~FixBitsMask::Map
;
180 return make_error
<StringError
>(
181 "Invalid first byte", std::make_error_code(std::errc::invalid_argument
));
184 template <class T
> Expected
<bool> Reader::readRaw(Object
&Obj
) {
185 if (sizeof(T
) > remainingSpace())
186 return make_error
<StringError
>(
187 "Invalid Raw with insufficient payload",
188 std::make_error_code(std::errc::invalid_argument
));
189 T Size
= endian::read
<T
, Endianness
>(Current
);
190 Current
+= sizeof(T
);
191 return createRaw(Obj
, Size
);
194 template <class T
> Expected
<bool> Reader::readInt(Object
&Obj
) {
195 if (sizeof(T
) > remainingSpace())
196 return make_error
<StringError
>(
197 "Invalid Int with insufficient payload",
198 std::make_error_code(std::errc::invalid_argument
));
199 Obj
.Int
= static_cast<int64_t>(endian::read
<T
, Endianness
>(Current
));
200 Current
+= sizeof(T
);
204 template <class T
> Expected
<bool> Reader::readUInt(Object
&Obj
) {
205 if (sizeof(T
) > remainingSpace())
206 return make_error
<StringError
>(
207 "Invalid Int with insufficient payload",
208 std::make_error_code(std::errc::invalid_argument
));
209 Obj
.UInt
= static_cast<uint64_t>(endian::read
<T
, Endianness
>(Current
));
210 Current
+= sizeof(T
);
214 template <class T
> Expected
<bool> Reader::readLength(Object
&Obj
) {
215 if (sizeof(T
) > remainingSpace())
216 return make_error
<StringError
>(
217 "Invalid Map/Array with invalid length",
218 std::make_error_code(std::errc::invalid_argument
));
219 Obj
.Length
= static_cast<size_t>(endian::read
<T
, Endianness
>(Current
));
220 Current
+= sizeof(T
);
224 template <class T
> Expected
<bool> Reader::readExt(Object
&Obj
) {
225 if (sizeof(T
) > remainingSpace())
226 return make_error
<StringError
>(
227 "Invalid Ext with invalid length",
228 std::make_error_code(std::errc::invalid_argument
));
229 T Size
= endian::read
<T
, Endianness
>(Current
);
230 Current
+= sizeof(T
);
231 return createExt(Obj
, Size
);
234 Expected
<bool> Reader::createRaw(Object
&Obj
, uint32_t Size
) {
235 if (Size
> remainingSpace())
236 return make_error
<StringError
>(
237 "Invalid Raw with insufficient payload",
238 std::make_error_code(std::errc::invalid_argument
));
239 Obj
.Raw
= StringRef(Current
, Size
);
244 Expected
<bool> Reader::createExt(Object
&Obj
, uint32_t Size
) {
246 return make_error
<StringError
>(
247 "Invalid Ext with no type",
248 std::make_error_code(std::errc::invalid_argument
));
249 Obj
.Extension
.Type
= *Current
++;
250 if (Size
> remainingSpace())
251 return make_error
<StringError
>(
252 "Invalid Ext with insufficient payload",
253 std::make_error_code(std::errc::invalid_argument
));
254 Obj
.Extension
.Bytes
= StringRef(Current
, Size
);