• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 5059503557

pending completion
5059503557

push

github

Benoit Blanchon
getOrAddMember

12 of 12 new or added lines in 2 files covered. (100.0%)

3287 of 3306 relevant lines covered (99.43%)

6225.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.63
/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2023, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Deserialization/deserialize.hpp>
8
#include <ArduinoJson/Memory/MemoryPool.hpp>
9
#include <ArduinoJson/MsgPack/endianess.hpp>
10
#include <ArduinoJson/MsgPack/ieee754.hpp>
11
#include <ArduinoJson/Polyfills/type_traits.hpp>
12
#include <ArduinoJson/Variant/VariantData.hpp>
13

14
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
15

16
template <typename TReader>
17
class MsgPackDeserializer {
18
 public:
19
  MsgPackDeserializer(MemoryPool* pool, TReader reader)
20
      : pool_(pool),
21
        reader_(reader),
22
        stringBuilder_(pool),
23
        foundSomething_(false) {}
24

25
  template <typename TFilter>
26
  DeserializationError parse(VariantData& variant, TFilter filter,
27
                             DeserializationOption::NestingLimit nestingLimit) {
28
    DeserializationError::Code err;
29
    err = parseVariant(&variant, filter, nestingLimit);
30
    return foundSomething_ ? err : DeserializationError::EmptyInput;
31
  }
32

33
 private:
34
  template <typename TFilter>
35
  DeserializationError::Code parseVariant(
36
      VariantData* variant, TFilter filter,
37
      DeserializationOption::NestingLimit nestingLimit) {
38
    DeserializationError::Code err;
39

40
    uint8_t code = 0;  // TODO: why do we need to initialize this variable?
41
    err = readByte(code);
42
    if (err)
43
      return err;
44

45
    foundSomething_ = true;
46

47
    bool allowValue = filter.allowValue();
48

49
    if (allowValue) {
50
      // callers pass a null pointer only when value must be ignored
51
      ARDUINOJSON_ASSERT(variant != 0);
52
    }
53

54
    switch (code) {
55
      case 0xc0:
56
        // already null
57
        return DeserializationError::Ok;
58

59
      case 0xc1:
60
        return DeserializationError::InvalidInput;
61

62
      case 0xc2:
63
        if (allowValue)
64
          variant->setBoolean(false);
65
        return DeserializationError::Ok;
66

67
      case 0xc3:
68
        if (allowValue)
69
          variant->setBoolean(true);
70
        return DeserializationError::Ok;
71

72
      case 0xc4:  // bin 8 (not supported)
73
        return skipString<uint8_t>();
74

75
      case 0xc5:  // bin 16 (not supported)
76
        return skipString<uint16_t>();
77

78
      case 0xc6:  // bin 32 (not supported)
79
        return skipString<uint32_t>();
80

81
      case 0xc7:  // ext 8 (not supported)
82
        return skipExt<uint8_t>();
83

84
      case 0xc8:  // ext 16 (not supported)
85
        return skipExt<uint16_t>();
86

87
      case 0xc9:  // ext 32 (not supported)
88
        return skipExt<uint32_t>();
89

90
      case 0xca:
91
        if (allowValue)
92
          return readFloat<float>(variant);
93
        else
94
          return skipBytes(4);
95

96
      case 0xcb:
97
        if (allowValue)
98
          return readDouble<double>(variant);
99
        else
100
          return skipBytes(8);
101

102
      case 0xcc:
103
        if (allowValue)
104
          return readInteger<uint8_t>(variant);
105
        else
106
          return skipBytes(1);
107

108
      case 0xcd:
109
        if (allowValue)
110
          return readInteger<uint16_t>(variant);
111
        else
112
          return skipBytes(2);
113

114
      case 0xce:
115
        if (allowValue)
116
          return readInteger<uint32_t>(variant);
117
        else
118
          return skipBytes(4);
119

120
      case 0xcf:
121
#if ARDUINOJSON_USE_LONG_LONG
122
        if (allowValue)
123
          return readInteger<uint64_t>(variant);
124
        else
125
          return skipBytes(8);
126
#else
127
        return skipBytes(8);  // not supported
128
#endif
129

130
      case 0xd0:
131
        if (allowValue)
132
          return readInteger<int8_t>(variant);
133
        else
134
          return skipBytes(1);
135

136
      case 0xd1:
137
        if (allowValue)
138
          return readInteger<int16_t>(variant);
139
        else
140
          return skipBytes(2);
141

142
      case 0xd2:
143
        if (allowValue)
144
          return readInteger<int32_t>(variant);
145
        else
146
          return skipBytes(4);
147

148
      case 0xd3:
149
#if ARDUINOJSON_USE_LONG_LONG
150
        if (allowValue)
151
          return readInteger<int64_t>(variant);
152
        else
153
          return skipBytes(8);  // not supported
154
#else
155
        return skipBytes(8);
156
#endif
157

158
      case 0xd4:  // fixext 1 (not supported)
159
        return skipBytes(2);
160

161
      case 0xd5:  // fixext 2 (not supported)
162
        return skipBytes(3);
163

164
      case 0xd6:  // fixext 4 (not supported)
165
        return skipBytes(5);
166

167
      case 0xd7:  // fixext 8 (not supported)
168
        return skipBytes(9);
169

170
      case 0xd8:  // fixext 16 (not supported)
171
        return skipBytes(17);
172

173
      case 0xd9:
174
        if (allowValue)
175
          return readString<uint8_t>(variant);
176
        else
177
          return skipString<uint8_t>();
178

179
      case 0xda:
180
        if (allowValue)
181
          return readString<uint16_t>(variant);
182
        else
183
          return skipString<uint16_t>();
184

185
      case 0xdb:
186
        if (allowValue)
187
          return readString<uint32_t>(variant);
188
        else
189
          return skipString<uint32_t>();
190

191
      case 0xdc:
192
        return readArray<uint16_t>(variant, filter, nestingLimit);
193

194
      case 0xdd:
195
        return readArray<uint32_t>(variant, filter, nestingLimit);
196

197
      case 0xde:
198
        return readObject<uint16_t>(variant, filter, nestingLimit);
199

200
      case 0xdf:
201
        return readObject<uint32_t>(variant, filter, nestingLimit);
202
    }
203

204
    switch (code & 0xf0) {
205
      case 0x80:
206
        return readObject(variant, code & 0x0F, filter, nestingLimit);
207

208
      case 0x90:
209
        return readArray(variant, code & 0x0F, filter, nestingLimit);
210
    }
211

212
    if ((code & 0xe0) == 0xa0) {
213
      if (allowValue)
214
        return readString(variant, code & 0x1f);
215
      else
216
        return skipBytes(code & 0x1f);
217
    }
218

219
    if (allowValue)
220
      variant->setInteger(static_cast<int8_t>(code));
221

222
    return DeserializationError::Ok;
223
  }
224

225
  DeserializationError::Code readByte(uint8_t& value) {
226
    int c = reader_.read();
227
    if (c < 0)
228
      return DeserializationError::IncompleteInput;
229
    value = static_cast<uint8_t>(c);
230
    return DeserializationError::Ok;
231
  }
232

233
  DeserializationError::Code readBytes(uint8_t* p, size_t n) {
234
    if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
235
      return DeserializationError::Ok;
236
    return DeserializationError::IncompleteInput;
237
  }
238

239
  template <typename T>
240
  DeserializationError::Code readBytes(T& value) {
241
    return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
242
  }
243

244
  DeserializationError::Code skipBytes(size_t n) {
245
    for (; n; --n) {
246
      if (reader_.read() < 0)
247
        return DeserializationError::IncompleteInput;
248
    }
249
    return DeserializationError::Ok;
250
  }
251

252
  template <typename T>
253
  DeserializationError::Code readInteger(T& value) {
254
    DeserializationError::Code err;
255

256
    err = readBytes(value);
257
    if (err)
258
      return err;
259

260
    fixEndianess(value);
261

262
    return DeserializationError::Ok;
263
  }
264

265
  template <typename T>
266
  DeserializationError::Code readInteger(VariantData* variant) {
267
    DeserializationError::Code err;
268
    T value;
269

270
    err = readInteger(value);
271
    if (err)
272
      return err;
273

274
    variant->setInteger(value);
275

276
    return DeserializationError::Ok;
277
  }
278

279
  template <typename T>
280
  typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
281
  readFloat(VariantData* variant) {
282
    DeserializationError::Code err;
283
    T value;
284

285
    err = readBytes(value);
286
    if (err)
287
      return err;
288

289
    fixEndianess(value);
290
    variant->setFloat(value);
291

292
    return DeserializationError::Ok;
293
  }
294

295
  template <typename T>
296
  typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
297
  readDouble(VariantData* variant) {
298
    DeserializationError::Code err;
299
    T value;
300

301
    err = readBytes(value);
302
    if (err)
303
      return err;
304

305
    fixEndianess(value);
306
    variant->setFloat(value);
307

308
    return DeserializationError::Ok;
309
  }
310

311
  template <typename T>
312
  typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
313
  readDouble(VariantData* variant) {
314
    DeserializationError::Code err;
315
    uint8_t i[8];  // input is 8 bytes
316
    T value;       // output is 4 bytes
317
    uint8_t* o = reinterpret_cast<uint8_t*>(&value);
318

319
    err = readBytes(i, 8);
320
    if (err)
321
      return err;
322

323
    doubleToFloat(i, o);
324
    fixEndianess(value);
325
    variant->setFloat(value);
326

327
    return DeserializationError::Ok;
328
  }
329

330
  template <typename T>
331
  DeserializationError::Code readString(VariantData* variant) {
332
    DeserializationError::Code err;
333
    T size;
334

335
    err = readInteger(size);
336
    if (err)
337
      return err;
338

339
    return readString(variant, size);
340
  }
341

342
  template <typename T>
343
  DeserializationError::Code readString() {
344
    DeserializationError::Code err;
345
    T size;
346

347
    err = readInteger(size);
348
    if (err)
349
      return err;
350

351
    return readString(size);
352
  }
353

354
  template <typename T>
355
  DeserializationError::Code skipString() {
356
    DeserializationError::Code err;
357
    T size;
358

359
    err = readInteger(size);
360
    if (err)
361
      return err;
362

363
    return skipBytes(size);
364
  }
365

366
  DeserializationError::Code readString(VariantData* variant, size_t n) {
367
    DeserializationError::Code err;
368

369
    err = readString(n);
370
    if (err)
371
      return err;
372

373
    variant->setString(stringBuilder_.save());
374
    return DeserializationError::Ok;
375
  }
376

377
  DeserializationError::Code readString(size_t n) {
378
    DeserializationError::Code err;
379

380
    stringBuilder_.startString();
381
    for (; n; --n) {
382
      uint8_t c;
383

384
      err = readBytes(c);
385
      if (err)
386
        return err;
387

388
      stringBuilder_.append(static_cast<char>(c));
389
    }
390

391
    if (!stringBuilder_.isValid())
392
      return DeserializationError::NoMemory;
393

394
    return DeserializationError::Ok;
395
  }
396

397
  template <typename TSize, typename TFilter>
398
  DeserializationError::Code readArray(
399
      VariantData* variant, TFilter filter,
400
      DeserializationOption::NestingLimit nestingLimit) {
401
    DeserializationError::Code err;
402
    TSize size;
403

404
    err = readInteger(size);
405
    if (err)
406
      return err;
407

408
    return readArray(variant, size, filter, nestingLimit);
409
  }
410

411
  template <typename TFilter>
412
  DeserializationError::Code readArray(
413
      VariantData* variant, size_t n, TFilter filter,
414
      DeserializationOption::NestingLimit nestingLimit) {
415
    DeserializationError::Code err;
416

417
    if (nestingLimit.reached())
418
      return DeserializationError::TooDeep;
419

420
    bool allowArray = filter.allowArray();
421

422
    CollectionData* array;
423
    if (allowArray) {
424
      ARDUINOJSON_ASSERT(variant != 0);
425
      array = &variant->toArray();
426
    } else {
427
      array = 0;
428
    }
429

430
    TFilter elementFilter = filter[0U];
431

432
    for (; n; --n) {
433
      VariantData* value;
434

435
      if (elementFilter.allow()) {
436
        ARDUINOJSON_ASSERT(array != 0);
437
        value = collectionAddElement(array, pool_);
438
        if (!value)
439
          return DeserializationError::NoMemory;
440
      } else {
441
        value = 0;
442
      }
443

444
      err = parseVariant(value, elementFilter, nestingLimit.decrement());
445
      if (err)
446
        return err;
447
    }
448

449
    return DeserializationError::Ok;
450
  }
451

452
  template <typename TSize, typename TFilter>
453
  DeserializationError::Code readObject(
454
      VariantData* variant, TFilter filter,
455
      DeserializationOption::NestingLimit nestingLimit) {
456
    DeserializationError::Code err;
457
    TSize size;
458

459
    err = readInteger(size);
460
    if (err)
461
      return err;
462

463
    return readObject(variant, size, filter, nestingLimit);
464
  }
465

466
  template <typename TFilter>
467
  DeserializationError::Code readObject(
468
      VariantData* variant, size_t n, TFilter filter,
469
      DeserializationOption::NestingLimit nestingLimit) {
470
    DeserializationError::Code err;
471

472
    if (nestingLimit.reached())
473
      return DeserializationError::TooDeep;
474

475
    CollectionData* object;
476
    if (filter.allowObject()) {
477
      ARDUINOJSON_ASSERT(variant != 0);
478
      object = &variant->toObject();
479
    } else {
480
      object = 0;
481
    }
482

483
    for (; n; --n) {
484
      err = readKey();
485
      if (err)
486
        return err;
487

488
      JsonString key = stringBuilder_.str();
489
      TFilter memberFilter = filter[key.c_str()];
490
      VariantData* member;
491

492
      if (memberFilter.allow()) {
493
        ARDUINOJSON_ASSERT(object != 0);
494

495
        // Save key in memory pool.
496
        auto savedKey = stringBuilder_.save();
497

498
        VariantSlot* slot = new (pool_) VariantSlot();
499
        if (!slot)
500
          return DeserializationError::NoMemory;
501

502
        slot->setKey(savedKey);
503
        object->add(slot);
504

505
        member = slot->data();
506
      } else {
507
        member = 0;
508
      }
509

510
      err = parseVariant(member, memberFilter, nestingLimit.decrement());
511
      if (err)
512
        return err;
513
    }
514

515
    return DeserializationError::Ok;
516
  }
517

518
  DeserializationError::Code readKey() {
519
    DeserializationError::Code err;
520
    uint8_t code;
521

522
    err = readByte(code);
523
    if (err)
524
      return err;
525

526
    if ((code & 0xe0) == 0xa0)
527
      return readString(code & 0x1f);
528

529
    switch (code) {
530
      case 0xd9:
531
        return readString<uint8_t>();
532

533
      case 0xda:
534
        return readString<uint16_t>();
535

536
      case 0xdb:
537
        return readString<uint32_t>();
538

539
      default:
540
        return DeserializationError::InvalidInput;
541
    }
542
  }
543

544
  template <typename T>
545
  DeserializationError::Code skipExt() {
546
    DeserializationError::Code err;
547
    T size;
548

549
    err = readInteger(size);
550
    if (err)
551
      return err;
552

553
    return skipBytes(size + 1U);
554
  }
555

556
  MemoryPool* pool_;
557
  TReader reader_;
558
  StringBuilder stringBuilder_;
559
  bool foundSomething_;
560
};
561

562
ARDUINOJSON_END_PRIVATE_NAMESPACE
563

564
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
565

566
// Parses a MessagePack input and puts the result in a JsonDocument.
567
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
568
template <typename... Args>
569
DeserializationError deserializeMsgPack(JsonDocument& doc, Args&&... args) {
570
  using namespace detail;
571
  return deserialize<MsgPackDeserializer>(doc, detail::forward<Args>(args)...);
572
}
573

574
// Parses a MessagePack input and puts the result in a JsonDocument.
575
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
576
template <typename TChar, typename... Args>
577
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
578
                                        Args&&... args) {
579
  using namespace detail;
580
  return deserialize<MsgPackDeserializer>(doc, input,
581
                                          detail::forward<Args>(args)...);
582
}
583

584
ARDUINOJSON_END_PUBLIC_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc