1//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements a MessagePack reader.
11///
12//===----------------------------------------------------------------------===//
13
14#include "llvm/BinaryFormat/MsgPackReader.h"
15#include "llvm/BinaryFormat/MsgPack.h"
16#include "llvm/Support/Endian.h"
17
18using namespace llvm;
19using namespace llvm::support;
20using namespace msgpack;
21
22Reader::Reader(MemoryBufferRef InputBuffer)
23 : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
24 End(InputBuffer.getBufferEnd()) {}
25
26Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
27
28Expected<bool> Reader::read(Object &Obj) {
29 if (Current == End)
30 return false;
31
32 uint8_t FB = static_cast<uint8_t>(*Current++);
33
34 switch (FB) {
35 case FirstByte::Nil:
36 Obj.Kind = Type::Nil;
37 return true;
38 case FirstByte::True:
39 Obj.Kind = Type::Boolean;
40 Obj.Bool = true;
41 return true;
42 case FirstByte::False:
43 Obj.Kind = Type::Boolean;
44 Obj.Bool = false;
45 return true;
46 case FirstByte::Int8:
47 Obj.Kind = Type::Int;
48 return readInt<int8_t>(Obj);
49 case FirstByte::Int16:
50 Obj.Kind = Type::Int;
51 return readInt<int16_t>(Obj);
52 case FirstByte::Int32:
53 Obj.Kind = Type::Int;
54 return readInt<int32_t>(Obj);
55 case FirstByte::Int64:
56 Obj.Kind = Type::Int;
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 Args: "Invalid Float32 with insufficient payload",
75 Args: std::make_error_code(e: std::errc::invalid_argument));
76 Obj.Float =
77 llvm::bit_cast<float>(from: endian::read<uint32_t, Endianness>(P: Current));
78 Current += sizeof(float);
79 return true;
80 case FirstByte::Float64:
81 Obj.Kind = Type::Float;
82 if (sizeof(double) > remainingSpace())
83 return make_error<StringError>(
84 Args: "Invalid Float64 with insufficient payload",
85 Args: std::make_error_code(e: std::errc::invalid_argument));
86 Obj.Float =
87 llvm::bit_cast<double>(from: endian::read<uint64_t, Endianness>(P: Current));
88 Current += sizeof(double);
89 return true;
90 case FirstByte::Str8:
91 Obj.Kind = Type::String;
92 return readRaw<uint8_t>(Obj);
93 case FirstByte::Str16:
94 Obj.Kind = Type::String;
95 return readRaw<uint16_t>(Obj);
96 case FirstByte::Str32:
97 Obj.Kind = Type::String;
98 return readRaw<uint32_t>(Obj);
99 case FirstByte::Bin8:
100 Obj.Kind = Type::Binary;
101 return readRaw<uint8_t>(Obj);
102 case FirstByte::Bin16:
103 Obj.Kind = Type::Binary;
104 return readRaw<uint16_t>(Obj);
105 case FirstByte::Bin32:
106 Obj.Kind = Type::Binary;
107 return readRaw<uint32_t>(Obj);
108 case FirstByte::Array16:
109 Obj.Kind = Type::Array;
110 return readLength<uint16_t>(Obj);
111 case FirstByte::Array32:
112 Obj.Kind = Type::Array;
113 return readLength<uint32_t>(Obj);
114 case FirstByte::Map16:
115 Obj.Kind = Type::Map;
116 return readLength<uint16_t>(Obj);
117 case FirstByte::Map32:
118 Obj.Kind = Type::Map;
119 return readLength<uint32_t>(Obj);
120 case FirstByte::FixExt1:
121 Obj.Kind = Type::Extension;
122 return createExt(Obj, Size: FixLen::Ext1);
123 case FirstByte::FixExt2:
124 Obj.Kind = Type::Extension;
125 return createExt(Obj, Size: FixLen::Ext2);
126 case FirstByte::FixExt4:
127 Obj.Kind = Type::Extension;
128 return createExt(Obj, Size: FixLen::Ext4);
129 case FirstByte::FixExt8:
130 Obj.Kind = Type::Extension;
131 return createExt(Obj, Size: FixLen::Ext8);
132 case FirstByte::FixExt16:
133 Obj.Kind = Type::Extension;
134 return createExt(Obj, Size: FixLen::Ext16);
135 case FirstByte::Ext8:
136 Obj.Kind = Type::Extension;
137 return readExt<uint8_t>(Obj);
138 case FirstByte::Ext16:
139 Obj.Kind = Type::Extension;
140 return readExt<uint16_t>(Obj);
141 case FirstByte::Ext32:
142 Obj.Kind = Type::Extension;
143 return readExt<uint32_t>(Obj);
144 }
145
146 if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
147 Obj.Kind = Type::Int;
148 int8_t I;
149 static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
150 memcpy(dest: &I, src: &FB, n: sizeof(FB));
151 Obj.Int = I;
152 return true;
153 }
154
155 if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
156 Obj.Kind = Type::UInt;
157 Obj.UInt = FB;
158 return true;
159 }
160
161 if ((FB & FixBitsMask::String) == FixBits::String) {
162 Obj.Kind = Type::String;
163 uint8_t Size = FB & ~FixBitsMask::String;
164 return createRaw(Obj, Size);
165 }
166
167 if ((FB & FixBitsMask::Array) == FixBits::Array) {
168 Obj.Kind = Type::Array;
169 Obj.Length = FB & ~FixBitsMask::Array;
170 return true;
171 }
172
173 if ((FB & FixBitsMask::Map) == FixBits::Map) {
174 Obj.Kind = Type::Map;
175 Obj.Length = FB & ~FixBitsMask::Map;
176 return true;
177 }
178
179 return make_error<StringError>(
180 Args: "Invalid first byte", Args: std::make_error_code(e: std::errc::invalid_argument));
181}
182
183template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
184 if (sizeof(T) > remainingSpace())
185 return make_error<StringError>(
186 Args: "Invalid Raw with insufficient payload",
187 Args: std::make_error_code(e: std::errc::invalid_argument));
188 T Size = endian::read<T, Endianness>(Current);
189 Current += sizeof(T);
190 return createRaw(Obj, Size);
191}
192
193template <class T> Expected<bool> Reader::readInt(Object &Obj) {
194 if (sizeof(T) > remainingSpace())
195 return make_error<StringError>(
196 Args: "Invalid Int with insufficient payload",
197 Args: std::make_error_code(e: std::errc::invalid_argument));
198 Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
199 Current += sizeof(T);
200 return true;
201}
202
203template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
204 if (sizeof(T) > remainingSpace())
205 return make_error<StringError>(
206 Args: "Invalid Int with insufficient payload",
207 Args: std::make_error_code(e: std::errc::invalid_argument));
208 Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
209 Current += sizeof(T);
210 return true;
211}
212
213template <class T> Expected<bool> Reader::readLength(Object &Obj) {
214 if (sizeof(T) > remainingSpace())
215 return make_error<StringError>(
216 Args: "Invalid Map/Array with invalid length",
217 Args: std::make_error_code(e: std::errc::invalid_argument));
218 Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
219 Current += sizeof(T);
220 return true;
221}
222
223template <class T> Expected<bool> Reader::readExt(Object &Obj) {
224 if (sizeof(T) > remainingSpace())
225 return make_error<StringError>(
226 Args: "Invalid Ext with invalid length",
227 Args: std::make_error_code(e: std::errc::invalid_argument));
228 T Size = endian::read<T, Endianness>(Current);
229 Current += sizeof(T);
230 return createExt(Obj, Size);
231}
232
233Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
234 if (Size > remainingSpace())
235 return make_error<StringError>(
236 Args: "Invalid Raw with insufficient payload",
237 Args: std::make_error_code(e: std::errc::invalid_argument));
238 Obj.Raw = StringRef(Current, Size);
239 Current += Size;
240 return true;
241}
242
243Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
244 if (Current == End)
245 return make_error<StringError>(
246 Args: "Invalid Ext with no type",
247 Args: std::make_error_code(e: std::errc::invalid_argument));
248 Obj.Extension.Type = *Current++;
249 if (Size > remainingSpace())
250 return make_error<StringError>(
251 Args: "Invalid Ext with insufficient payload",
252 Args: std::make_error_code(e: std::errc::invalid_argument));
253 Obj.Extension.Bytes = StringRef(Current, Size);
254 Current += Size;
255 return true;
256}
257