xref: /freebsd/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
18 using namespace llvm;
19 using namespace llvm::support;
20 using namespace msgpack;
21 
22 Reader::Reader(MemoryBufferRef InputBuffer)
23     : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
24       End(InputBuffer.getBufferEnd()) {}
25 
26 Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
27 
28 Expected<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           "Invalid Float32 with insufficient payload",
75           std::make_error_code(std::errc::invalid_argument));
76     Obj.Float =
77         llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(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           "Invalid Float64 with insufficient payload",
85           std::make_error_code(std::errc::invalid_argument));
86     Obj.Float =
87         llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(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, FixLen::Ext1);
123   case FirstByte::FixExt2:
124     Obj.Kind = Type::Extension;
125     return createExt(Obj, FixLen::Ext2);
126   case FirstByte::FixExt4:
127     Obj.Kind = Type::Extension;
128     return createExt(Obj, FixLen::Ext4);
129   case FirstByte::FixExt8:
130     Obj.Kind = Type::Extension;
131     return createExt(Obj, FixLen::Ext8);
132   case FirstByte::FixExt16:
133     Obj.Kind = Type::Extension;
134     return createExt(Obj, 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(&I, &FB, 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       "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
181 }
182 
183 template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
184   if (sizeof(T) > remainingSpace())
185     return make_error<StringError>(
186         "Invalid Raw with insufficient payload",
187         std::make_error_code(std::errc::invalid_argument));
188   T Size = endian::read<T, Endianness>(Current);
189   Current += sizeof(T);
190   return createRaw(Obj, Size);
191 }
192 
193 template <class T> Expected<bool> Reader::readInt(Object &Obj) {
194   if (sizeof(T) > remainingSpace())
195     return make_error<StringError>(
196         "Invalid Int with insufficient payload",
197         std::make_error_code(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 
203 template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
204   if (sizeof(T) > remainingSpace())
205     return make_error<StringError>(
206         "Invalid Int with insufficient payload",
207         std::make_error_code(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 
213 template <class T> Expected<bool> Reader::readLength(Object &Obj) {
214   if (sizeof(T) > remainingSpace())
215     return make_error<StringError>(
216         "Invalid Map/Array with invalid length",
217         std::make_error_code(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 
223 template <class T> Expected<bool> Reader::readExt(Object &Obj) {
224   if (sizeof(T) > remainingSpace())
225     return make_error<StringError>(
226         "Invalid Ext with invalid length",
227         std::make_error_code(std::errc::invalid_argument));
228   T Size = endian::read<T, Endianness>(Current);
229   Current += sizeof(T);
230   return createExt(Obj, Size);
231 }
232 
233 Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
234   if (Size > remainingSpace())
235     return make_error<StringError>(
236         "Invalid Raw with insufficient payload",
237         std::make_error_code(std::errc::invalid_argument));
238   Obj.Raw = StringRef(Current, Size);
239   Current += Size;
240   return true;
241 }
242 
243 Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
244   if (Current == End)
245     return make_error<StringError>(
246         "Invalid Ext with no type",
247         std::make_error_code(std::errc::invalid_argument));
248   Obj.Extension.Type = *Current++;
249   if (Size > remainingSpace())
250     return make_error<StringError>(
251         "Invalid Ext with insufficient payload",
252         std::make_error_code(std::errc::invalid_argument));
253   Obj.Extension.Bytes = StringRef(Current, Size);
254   Current += Size;
255   return true;
256 }
257