/src/arduinojson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // ArduinoJson - https://arduinojson.org |
2 | | // Copyright © 2014-2024, Benoit BLANCHON |
3 | | // MIT License |
4 | | |
5 | | #pragma once |
6 | | |
7 | | #include <ArduinoJson/Deserialization/deserialize.hpp> |
8 | | #include <ArduinoJson/Memory/ResourceManager.hpp> |
9 | | #include <ArduinoJson/Memory/StringBuffer.hpp> |
10 | | #include <ArduinoJson/MsgPack/endianness.hpp> |
11 | | #include <ArduinoJson/MsgPack/ieee754.hpp> |
12 | | #include <ArduinoJson/Polyfills/type_traits.hpp> |
13 | | #include <ArduinoJson/Variant/VariantData.hpp> |
14 | | |
15 | | ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE |
16 | | |
17 | | template <typename TReader> |
18 | | class MsgPackDeserializer { |
19 | | public: |
20 | | MsgPackDeserializer(ResourceManager* resources, TReader reader) |
21 | | : resources_(resources), |
22 | | reader_(reader), |
23 | | stringBuffer_(resources), |
24 | 1.46k | foundSomething_(false) {} |
25 | | |
26 | | template <typename TFilter> |
27 | | DeserializationError parse(VariantData& variant, TFilter filter, |
28 | 1.46k | DeserializationOption::NestingLimit nestingLimit) { |
29 | 1.46k | DeserializationError::Code err; |
30 | 1.46k | err = parseVariant(&variant, filter, nestingLimit); |
31 | 1.46k | return foundSomething_ ? err : DeserializationError::EmptyInput; |
32 | 1.46k | } |
33 | | |
34 | | private: |
35 | | template <typename TFilter> |
36 | | DeserializationError::Code parseVariant( |
37 | | VariantData* variant, TFilter filter, |
38 | 14.6k | DeserializationOption::NestingLimit nestingLimit) { |
39 | 14.6k | DeserializationError::Code err; |
40 | | |
41 | 14.6k | uint8_t header[5]; |
42 | 14.6k | err = readBytes(header, 1); |
43 | 14.6k | if (err) |
44 | 235 | return err; |
45 | | |
46 | 14.4k | const uint8_t& code = header[0]; |
47 | | |
48 | 14.4k | foundSomething_ = true; |
49 | | |
50 | 14.4k | bool allowValue = filter.allowValue(); |
51 | | |
52 | 14.4k | if (allowValue) { |
53 | | // callers pass a null pointer only when value must be ignored |
54 | 14.4k | ARDUINOJSON_ASSERT(variant != 0); |
55 | 14.4k | } |
56 | | |
57 | 14.4k | if (code >= 0xcc && code <= 0xd3) { |
58 | 865 | auto width = uint8_t(1U << ((code - 0xcc) % 4)); |
59 | 865 | if (allowValue) |
60 | 865 | return readInteger(variant, width, code >= 0xd0); |
61 | 0 | else |
62 | 0 | return skipBytes(width); |
63 | 865 | } |
64 | | |
65 | 13.5k | switch (code) { |
66 | 215 | case 0xc0: |
67 | | // already null |
68 | 215 | return DeserializationError::Ok; |
69 | | |
70 | 3 | case 0xc1: |
71 | 3 | return DeserializationError::InvalidInput; |
72 | | |
73 | 212 | case 0xc2: |
74 | 416 | case 0xc3: |
75 | 416 | if (allowValue) |
76 | 416 | variant->setBoolean(code == 0xc3); |
77 | 416 | return DeserializationError::Ok; |
78 | | |
79 | 416 | case 0xca: |
80 | 416 | if (allowValue) |
81 | 416 | return readFloat<float>(variant); |
82 | 0 | else |
83 | 0 | return skipBytes(4); |
84 | | |
85 | 150 | case 0xcb: |
86 | 150 | if (allowValue) |
87 | 150 | return readDouble<double>(variant); |
88 | 0 | else |
89 | 0 | return skipBytes(8); |
90 | 13.5k | } |
91 | | |
92 | 12.3k | if (code <= 0x7f || code >= 0xe0) { // fixint |
93 | 3.97k | if (allowValue) |
94 | 3.97k | variant->setInteger(static_cast<int8_t>(code), resources_); |
95 | 3.97k | return DeserializationError::Ok; |
96 | 3.97k | } |
97 | | |
98 | 8.39k | uint8_t sizeBytes = 0; |
99 | 8.39k | size_t size = 0; |
100 | 8.39k | bool isExtension = code >= 0xc7 && code <= 0xc9; |
101 | | |
102 | 8.39k | switch (code) { |
103 | 455 | case 0xc4: // bin 8 |
104 | 573 | case 0xc7: // ext 8 |
105 | 940 | case 0xd9: // str 8 |
106 | 940 | sizeBytes = 1; |
107 | 940 | break; |
108 | | |
109 | 94 | case 0xc5: // bin 16 |
110 | 171 | case 0xc8: // ext 16 |
111 | 330 | case 0xda: // str 16 |
112 | 534 | case 0xdc: // array 16 |
113 | 699 | case 0xde: // map 16 |
114 | 699 | sizeBytes = 2; |
115 | 699 | break; |
116 | | |
117 | 105 | case 0xc6: // bin 32 |
118 | 183 | case 0xc9: // ext 32 |
119 | 384 | case 0xdb: // str 32 |
120 | 597 | case 0xdd: // array 32 |
121 | 746 | case 0xdf: // map 32 |
122 | 746 | sizeBytes = 4; |
123 | 746 | break; |
124 | 8.39k | } |
125 | | |
126 | 8.39k | if (code >= 0xd4 && code <= 0xd8) { // fixext |
127 | 173 | size = size_t(1) << (code - 0xd4); |
128 | 173 | isExtension = true; |
129 | 173 | } |
130 | | |
131 | 8.39k | switch (code & 0xf0) { |
132 | 2.67k | case 0x90: // fixarray |
133 | 3.56k | case 0x80: // fixmap |
134 | 3.56k | size = code & 0x0F; |
135 | 3.56k | break; |
136 | 8.39k | } |
137 | | |
138 | 8.39k | switch (code & 0xe0) { |
139 | 2.27k | case 0xa0: // fixstr |
140 | 2.27k | size = code & 0x1f; |
141 | 2.27k | break; |
142 | 8.39k | } |
143 | | |
144 | 8.39k | if (sizeBytes) { |
145 | 2.38k | err = readBytes(header + 1, sizeBytes); |
146 | 2.38k | if (err) |
147 | 102 | return err; |
148 | | |
149 | 2.28k | uint32_t size32 = 0; |
150 | 7.34k | for (uint8_t i = 0; i < sizeBytes; i++) |
151 | 5.05k | size32 = (size32 << 8) | header[i + 1]; |
152 | | |
153 | 2.28k | size = size_t(size32); |
154 | 2.28k | if (size < size32) // integer overflow |
155 | 0 | return DeserializationError::NoMemory; // (not testable on 32/64-bit) |
156 | 2.28k | } |
157 | | |
158 | | // array 16, 32 and fixarray |
159 | 8.29k | if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90) |
160 | 3.07k | return readArray(variant, size, filter, nestingLimit); |
161 | | |
162 | | // map 16, 32 and fixmap |
163 | 5.22k | if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80) |
164 | 1.18k | return readObject(variant, size, filter, nestingLimit); |
165 | | |
166 | | // str 8, 16, 32 and fixstr |
167 | 4.03k | if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) { |
168 | 2.98k | if (allowValue) |
169 | 2.98k | return readString(variant, size); |
170 | 0 | else |
171 | 0 | return skipBytes(size); |
172 | 2.98k | } |
173 | | |
174 | 1.05k | if (isExtension) |
175 | 425 | size++; // to include the type |
176 | | |
177 | 1.05k | if (allowValue) |
178 | 1.05k | return readRawString(variant, header, uint8_t(1 + sizeBytes), size); |
179 | 0 | else |
180 | 0 | return skipBytes(size); |
181 | 1.05k | } |
182 | | |
183 | 2.76k | DeserializationError::Code readByte(uint8_t& value) { |
184 | 2.76k | int c = reader_.read(); |
185 | 2.76k | if (c < 0) |
186 | 74 | return DeserializationError::IncompleteInput; |
187 | 2.69k | value = static_cast<uint8_t>(c); |
188 | 2.69k | return DeserializationError::Ok; |
189 | 2.76k | } |
190 | | |
191 | 24.5k | DeserializationError::Code readBytes(void* p, size_t n) { |
192 | 24.5k | if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n) |
193 | 23.9k | return DeserializationError::Ok; |
194 | 568 | return DeserializationError::IncompleteInput; |
195 | 24.5k | } |
196 | | |
197 | | template <typename T> |
198 | 566 | DeserializationError::Code readBytes(T& value) { |
199 | 566 | return readBytes(&value, sizeof(value)); |
200 | 566 | } ArduinoJson::V710HB42::DeserializationError::Code ArduinoJson::V710HB42::detail::MsgPackDeserializer<ArduinoJson::V710HB42::detail::BoundedReader<unsigned char const*, void> >::readBytes<float>(float&) Line | Count | Source | 198 | 416 | DeserializationError::Code readBytes(T& value) { | 199 | 416 | return readBytes(&value, sizeof(value)); | 200 | 416 | } |
ArduinoJson::V710HB42::DeserializationError::Code ArduinoJson::V710HB42::detail::MsgPackDeserializer<ArduinoJson::V710HB42::detail::BoundedReader<unsigned char const*, void> >::readBytes<double>(double&) Line | Count | Source | 198 | 150 | DeserializationError::Code readBytes(T& value) { | 199 | 150 | return readBytes(&value, sizeof(value)); | 200 | 150 | } |
|
201 | | |
202 | 0 | DeserializationError::Code skipBytes(size_t n) { |
203 | 0 | for (; n; --n) { |
204 | 0 | if (reader_.read() < 0) |
205 | 0 | return DeserializationError::IncompleteInput; |
206 | 0 | } |
207 | 0 | return DeserializationError::Ok; |
208 | 0 | } |
209 | | |
210 | | DeserializationError::Code readInteger(VariantData* variant, uint8_t width, |
211 | 865 | bool isSigned) { |
212 | 865 | uint8_t buffer[8]; |
213 | | |
214 | 865 | auto err = readBytes(buffer, width); |
215 | 865 | if (err) |
216 | 17 | return err; |
217 | | |
218 | 848 | union { |
219 | 848 | int64_t signedValue; |
220 | 848 | uint64_t unsignedValue; |
221 | 848 | }; |
222 | | |
223 | 848 | if (isSigned) |
224 | 441 | signedValue = static_cast<int8_t>(buffer[0]); // propagate sign bit |
225 | 407 | else |
226 | 407 | unsignedValue = static_cast<uint8_t>(buffer[0]); |
227 | | |
228 | 3.62k | for (uint8_t i = 1; i < width; i++) |
229 | 2.77k | unsignedValue = (unsignedValue << 8) | buffer[i]; |
230 | | |
231 | 848 | if (isSigned) { |
232 | 441 | auto truncatedValue = static_cast<JsonInteger>(signedValue); |
233 | 441 | if (truncatedValue == signedValue) { |
234 | 441 | if (!variant->setInteger(truncatedValue, resources_)) |
235 | 0 | return DeserializationError::NoMemory; |
236 | 441 | } |
237 | | // else set null on overflow |
238 | 441 | } else { |
239 | 407 | auto truncatedValue = static_cast<JsonUInt>(unsignedValue); |
240 | 407 | if (truncatedValue == unsignedValue) |
241 | 407 | if (!variant->setInteger(truncatedValue, resources_)) |
242 | 0 | return DeserializationError::NoMemory; |
243 | | // else set null on overflow |
244 | 407 | } |
245 | | |
246 | 848 | return DeserializationError::Ok; |
247 | 848 | } |
248 | | |
249 | | template <typename T> |
250 | | enable_if_t<sizeof(T) == 4, DeserializationError::Code> readFloat( |
251 | 416 | VariantData* variant) { |
252 | 416 | DeserializationError::Code err; |
253 | 416 | T value; |
254 | | |
255 | 416 | err = readBytes(value); |
256 | 416 | if (err) |
257 | 8 | return err; |
258 | | |
259 | 408 | fixEndianness(value); |
260 | 408 | variant->setFloat(value, resources_); |
261 | | |
262 | 408 | return DeserializationError::Ok; |
263 | 416 | } |
264 | | |
265 | | template <typename T> |
266 | | enable_if_t<sizeof(T) == 8, DeserializationError::Code> readDouble( |
267 | 150 | VariantData* variant) { |
268 | 150 | DeserializationError::Code err; |
269 | 150 | T value; |
270 | | |
271 | 150 | err = readBytes(value); |
272 | 150 | if (err) |
273 | 14 | return err; |
274 | | |
275 | 136 | fixEndianness(value); |
276 | 136 | if (variant->setFloat(value, resources_)) |
277 | 136 | return DeserializationError::Ok; |
278 | 0 | else |
279 | 0 | return DeserializationError::NoMemory; |
280 | 136 | } |
281 | | |
282 | | template <typename T> |
283 | | enable_if_t<sizeof(T) == 4, DeserializationError::Code> readDouble( |
284 | | VariantData* variant) { |
285 | | DeserializationError::Code err; |
286 | | uint8_t i[8]; // input is 8 bytes |
287 | | T value; // output is 4 bytes |
288 | | uint8_t* o = reinterpret_cast<uint8_t*>(&value); |
289 | | |
290 | | err = readBytes(i, 8); |
291 | | if (err) |
292 | | return err; |
293 | | |
294 | | doubleToFloat(i, o); |
295 | | fixEndianness(value); |
296 | | variant->setFloat(value, resources_); |
297 | | |
298 | | return DeserializationError::Ok; |
299 | | } |
300 | | |
301 | 2.98k | DeserializationError::Code readString(VariantData* variant, size_t n) { |
302 | 2.98k | DeserializationError::Code err; |
303 | | |
304 | 2.98k | err = readString(n); |
305 | 2.98k | if (err) |
306 | 112 | return err; |
307 | | |
308 | 2.86k | variant->setOwnedString(stringBuffer_.save()); |
309 | 2.86k | return DeserializationError::Ok; |
310 | 2.98k | } |
311 | | |
312 | 5.11k | DeserializationError::Code readString(size_t n) { |
313 | 5.11k | char* p = stringBuffer_.reserve(n); |
314 | 5.11k | if (!p) |
315 | 39 | return DeserializationError::NoMemory; |
316 | | |
317 | 5.07k | return readBytes(p, n); |
318 | 5.11k | } |
319 | | |
320 | | DeserializationError::Code readRawString(VariantData* variant, |
321 | | const void* header, |
322 | 1.05k | uint8_t headerSize, size_t n) { |
323 | 1.05k | auto totalSize = size_t(headerSize + n); |
324 | 1.05k | if (totalSize < n) // integer overflow |
325 | 0 | return DeserializationError::NoMemory; // (not testable on 64-bit) |
326 | | |
327 | 1.05k | char* p = stringBuffer_.reserve(totalSize); |
328 | 1.05k | if (!p) |
329 | 52 | return DeserializationError::NoMemory; |
330 | | |
331 | 1.00k | memcpy(p, header, headerSize); |
332 | | |
333 | 1.00k | auto err = readBytes(p + headerSize, n); |
334 | 1.00k | if (err) |
335 | 97 | return err; |
336 | | |
337 | 909 | variant->setRawString(stringBuffer_.save()); |
338 | 909 | return DeserializationError::Ok; |
339 | 1.00k | } |
340 | | |
341 | | template <typename TFilter> |
342 | | DeserializationError::Code readArray( |
343 | | VariantData* variant, size_t n, TFilter filter, |
344 | 3.07k | DeserializationOption::NestingLimit nestingLimit) { |
345 | 3.07k | DeserializationError::Code err; |
346 | | |
347 | 3.07k | if (nestingLimit.reached()) |
348 | 4 | return DeserializationError::TooDeep; |
349 | | |
350 | 3.07k | bool allowArray = filter.allowArray(); |
351 | | |
352 | 3.07k | ArrayData* array; |
353 | 3.07k | if (allowArray) { |
354 | 3.07k | ARDUINOJSON_ASSERT(variant != 0); |
355 | 3.07k | array = &variant->toArray(); |
356 | 3.07k | } else { |
357 | 0 | array = 0; |
358 | 0 | } |
359 | | |
360 | 3.07k | TFilter elementFilter = filter[0U]; |
361 | | |
362 | 13.4k | for (; n; --n) { |
363 | 11.0k | VariantData* value; |
364 | | |
365 | 11.0k | if (elementFilter.allow()) { |
366 | 11.0k | ARDUINOJSON_ASSERT(array != 0); |
367 | 11.0k | value = array->addElement(resources_); |
368 | 11.0k | if (!value) |
369 | 0 | return DeserializationError::NoMemory; |
370 | 11.0k | } else { |
371 | 0 | value = 0; |
372 | 0 | } |
373 | | |
374 | 11.0k | err = parseVariant(value, elementFilter, nestingLimit.decrement()); |
375 | 11.0k | if (err) |
376 | 743 | return err; |
377 | 11.0k | } |
378 | | |
379 | 2.32k | return DeserializationError::Ok; |
380 | 3.07k | } |
381 | | |
382 | | template <typename TFilter> |
383 | | DeserializationError::Code readObject( |
384 | | VariantData* variant, size_t n, TFilter filter, |
385 | 1.18k | DeserializationOption::NestingLimit nestingLimit) { |
386 | 1.18k | DeserializationError::Code err; |
387 | | |
388 | 1.18k | if (nestingLimit.reached()) |
389 | 1 | return DeserializationError::TooDeep; |
390 | | |
391 | 1.18k | ObjectData* object; |
392 | 1.18k | if (filter.allowObject()) { |
393 | 1.18k | ARDUINOJSON_ASSERT(variant != 0); |
394 | 1.18k | object = &variant->toObject(); |
395 | 1.18k | } else { |
396 | 0 | object = 0; |
397 | 0 | } |
398 | | |
399 | 3.16k | for (; n; --n) { |
400 | 2.22k | err = readKey(); |
401 | 2.22k | if (err) |
402 | 116 | return err; |
403 | | |
404 | 2.10k | JsonString key = stringBuffer_.str(); |
405 | 2.10k | TFilter memberFilter = filter[key.c_str()]; |
406 | 2.10k | VariantData* member; |
407 | | |
408 | 2.10k | if (memberFilter.allow()) { |
409 | 2.10k | ARDUINOJSON_ASSERT(object != 0); |
410 | | |
411 | | // Save key in memory pool. |
412 | 2.10k | auto savedKey = stringBuffer_.save(); |
413 | | |
414 | 2.10k | member = object->addMember(savedKey, resources_); |
415 | 2.10k | if (!member) |
416 | 0 | return DeserializationError::NoMemory; |
417 | 2.10k | } else { |
418 | 0 | member = 0; |
419 | 0 | } |
420 | | |
421 | 2.10k | err = parseVariant(member, memberFilter, nestingLimit.decrement()); |
422 | 2.10k | if (err) |
423 | 120 | return err; |
424 | 2.10k | } |
425 | | |
426 | 945 | return DeserializationError::Ok; |
427 | 1.18k | } |
428 | | |
429 | 2.22k | DeserializationError::Code readKey() { |
430 | 2.22k | DeserializationError::Code err; |
431 | 2.22k | uint8_t code; |
432 | | |
433 | 2.22k | err = readByte(code); |
434 | 2.22k | if (err) |
435 | 61 | return err; |
436 | | |
437 | 2.16k | if ((code & 0xe0) == 0xa0) |
438 | 1.94k | return readString(code & 0x1f); |
439 | | |
440 | 216 | if (code >= 0xd9 && code <= 0xdb) { |
441 | 196 | uint8_t sizeBytes = uint8_t(1U << (code - 0xd9)); |
442 | 196 | uint32_t size = 0; |
443 | 726 | for (uint8_t i = 0; i < sizeBytes; i++) { |
444 | 543 | err = readByte(code); |
445 | 543 | if (err) |
446 | 13 | return err; |
447 | 530 | size = (size << 8) | code; |
448 | 530 | } |
449 | 183 | return readString(size); |
450 | 196 | } |
451 | | |
452 | 20 | return DeserializationError::InvalidInput; |
453 | 216 | } |
454 | | |
455 | | ResourceManager* resources_; |
456 | | TReader reader_; |
457 | | StringBuffer stringBuffer_; |
458 | | bool foundSomething_; |
459 | | }; |
460 | | |
461 | | ARDUINOJSON_END_PRIVATE_NAMESPACE |
462 | | |
463 | | ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE |
464 | | |
465 | | // Parses a MessagePack input and puts the result in a JsonDocument. |
466 | | // https://arduinojson.org/v7/api/msgpack/deserializemsgpack/ |
467 | | template <typename TDestination, typename... Args> |
468 | | detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, |
469 | | DeserializationError> |
470 | | deserializeMsgPack(TDestination&& dst, Args&&... args) { |
471 | | using namespace detail; |
472 | | return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst), |
473 | | detail::forward<Args>(args)...); |
474 | | } |
475 | | |
476 | | // Parses a MessagePack input and puts the result in a JsonDocument. |
477 | | // https://arduinojson.org/v7/api/msgpack/deserializemsgpack/ |
478 | | template <typename TDestination, typename TChar, typename... Args> |
479 | | detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, |
480 | | DeserializationError> |
481 | 1.46k | deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) { |
482 | 1.46k | using namespace detail; |
483 | 1.46k | return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst), |
484 | 1.46k | input, |
485 | 1.46k | detail::forward<Args>(args)...); |
486 | 1.46k | } |
487 | | |
488 | | ARDUINOJSON_END_PUBLIC_NAMESPACE |