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

bblanchon / ArduinoJson / 4766013433

pending completion
4766013433

push

github

Benoit Blanchon
Increase coverage

8 of 8 new or added lines in 3 files covered. (100.0%)

3321 of 3342 relevant lines covered (99.37%)

6648.12 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, typename TStringStorage>
17
class MsgPackDeserializer {
18
 public:
19
  MsgPackDeserializer(MemoryPool* pool, TReader reader,
466✔
20
                      TStringStorage stringStorage)
21
      : _pool(pool),
22
        _reader(reader),
23
        _stringStorage(stringStorage),
24
        _foundSomething(false) {}
466✔
25

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

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

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

46
    _foundSomething = true;
807✔
47

48
    bool allowValue = filter.allowValue();
807✔
49

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

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

60
      case 0xc1:
1✔
61
        return DeserializationError::InvalidInput;
1✔
62

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

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

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

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

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

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

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

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

91
      case 0xca:
20✔
92
        if (allowValue)
20✔
93
          return readFloat<float>(variant);
11✔
94
        else
95
          return skipBytes(4);
9✔
96

97
      case 0xcb:
19✔
98
        if (allowValue)
19✔
99
          return readDouble<double>(variant);
16✔
100
        else
101
          return skipBytes(8);
3✔
102

103
      case 0xcc:
10✔
104
        if (allowValue)
10✔
105
          return readInteger<uint8_t>(variant);
6✔
106
        else
107
          return skipBytes(1);
4✔
108

109
      case 0xcd:
11✔
110
        if (allowValue)
11✔
111
          return readInteger<uint16_t>(variant);
8✔
112
        else
113
          return skipBytes(2);
3✔
114

115
      case 0xce:
12✔
116
        if (allowValue)
12✔
117
          return readInteger<uint32_t>(variant);
9✔
118
        else
119
          return skipBytes(4);
3✔
120

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

131
      case 0xd0:
7✔
132
        if (allowValue)
7✔
133
          return readInteger<int8_t>(variant);
4✔
134
        else
135
          return skipBytes(1);
3✔
136

137
      case 0xd1:
9✔
138
        if (allowValue)
9✔
139
          return readInteger<int16_t>(variant);
6✔
140
        else
141
          return skipBytes(2);
3✔
142

143
      case 0xd2:
11✔
144
        if (allowValue)
11✔
145
          return readInteger<int32_t>(variant);
8✔
146
        else
147
          return skipBytes(4);
3✔
148

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

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

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

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

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

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

174
      case 0xd9:
14✔
175
        if (allowValue)
14✔
176
          return readString<uint8_t>(variant);
10✔
177
        else
178
          return skipString<uint8_t>();
4✔
179

180
      case 0xda:
14✔
181
        if (allowValue)
14✔
182
          return readString<uint16_t>(variant);
11✔
183
        else
184
          return skipString<uint16_t>();
3✔
185

186
      case 0xdb:
16✔
187
        if (allowValue)
16✔
188
          return readString<uint32_t>(variant);
13✔
189
        else
190
          return skipString<uint32_t>();
3✔
191

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

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

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

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

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

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

213
    if ((code & 0xe0) == 0xa0) {
252✔
214
      if (allowValue)
44✔
215
        return readString(variant, code & 0x1f);
34✔
216
      else
217
        return skipBytes(code & 0x1f);
10✔
218
    }
219

220
    if (allowValue)
208✔
221
      variant->setInteger(static_cast<int8_t>(code));
160✔
222

223
    return DeserializationError::Ok;
208✔
224
  }
225

226
  DeserializationError::Code readByte(uint8_t& value) {
1,107✔
227
    int c = _reader.read();
1,107✔
228
    if (c < 0)
1,107✔
229
      return DeserializationError::IncompleteInput;
15✔
230
    value = static_cast<uint8_t>(c);
1,092✔
231
    return DeserializationError::Ok;
1,092✔
232
  }
233

234
  DeserializationError::Code readBytes(uint8_t* p, size_t n) {
2,235✔
235
    if (_reader.readBytes(reinterpret_cast<char*>(p), n) == n)
2,235✔
236
      return DeserializationError::Ok;
2,115✔
237
    return DeserializationError::IncompleteInput;
120✔
238
  }
239

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

245
  DeserializationError::Code skipBytes(size_t n) {
738✔
246
    for (; n; --n) {
738✔
247
      if (_reader.read() < 0)
650✔
248
        return DeserializationError::IncompleteInput;
46✔
249
    }
250
    return DeserializationError::Ok;
88✔
251
  }
252

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

257
    err = readBytes(value);
243✔
258
    if (err)
243✔
259
      return err;
70✔
260

261
    fixEndianess(value);
173✔
262

263
    return DeserializationError::Ok;
173✔
264
  }
265

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

271
    err = readInteger(value);
65✔
272
    if (err)
65✔
273
      return err;
30✔
274

275
    variant->setInteger(value);
35✔
276

277
    return DeserializationError::Ok;
35✔
278
  }
279

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

286
    err = readBytes(value);
11✔
287
    if (err)
11✔
288
      return err;
4✔
289

290
    fixEndianess(value);
7✔
291
    variant->setFloat(value);
7✔
292

293
    return DeserializationError::Ok;
7✔
294
  }
295

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

302
    err = readBytes(value);
16✔
303
    if (err)
16✔
304
      return err;
8✔
305

306
    fixEndianess(value);
8✔
307
    variant->setFloat(value);
8✔
308

309
    return DeserializationError::Ok;
8✔
310
  }
311

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

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

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

328
    return DeserializationError::Ok;
329
  }
330

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

336
    err = readInteger(size);
34✔
337
    if (err)
34✔
338
      return err;
7✔
339

340
    return readString(variant, size);
27✔
341
  }
342

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

348
    err = readInteger(size);
12✔
349
    if (err)
12✔
350
      return err;
1✔
351

352
    return readString(size);
11✔
353
  }
354

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

360
    err = readInteger(size);
29✔
361
    if (err)
29✔
362
      return err;
8✔
363

364
    return skipBytes(size);
21✔
365
  }
366

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

370
    err = readString(n);
61✔
371
    if (err)
61✔
372
      return err;
30✔
373

374
    variant->setString(_stringStorage.save());
33✔
375
    return DeserializationError::Ok;
31✔
376
  }
377

378
  DeserializationError::Code readString(size_t n) {
344✔
379
    DeserializationError::Code err;
380

381
    _stringStorage.startString();
344✔
382
    for (; n; --n) {
2,271✔
383
      uint8_t c;
384

385
      err = readBytes(c);
1,965✔
386
      if (err)
1,965✔
387
        return err;
38✔
388

389
      _stringStorage.append(static_cast<char>(c));
1,927✔
390
    }
391

392
    if (!_stringStorage.isValid())
306✔
393
      return DeserializationError::NoMemory;
10✔
394

395
    return DeserializationError::Ok;
296✔
396
  }
397

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

405
    err = readInteger(size);
29✔
406
    if (err)
29✔
407
      return err;
6✔
408

409
    return readArray(variant, size, filter, nestingLimit);
23✔
410
  }
411

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

418
    if (nestingLimit.reached())
77✔
419
      return DeserializationError::TooDeep;
9✔
420

421
    bool allowArray = filter.allowArray();
68✔
422

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

431
    TFilter memberFilter = filter[0U];
68✔
432

433
    for (; n; --n) {
143✔
434
      VariantData* value;
435

436
      if (memberFilter.allow()) {
93✔
437
        ARDUINOJSON_ASSERT(array != 0);
438
        value = collectionAddElement(array, _pool);
71✔
439
        if (!value)
71✔
440
          return DeserializationError::NoMemory;
6✔
441
      } else {
442
        value = 0;
22✔
443
      }
444

445
      err = parseVariant(value, memberFilter, nestingLimit.decrement());
87✔
446
      if (err)
87✔
447
        return err;
12✔
448
    }
449

450
    return DeserializationError::Ok;
50✔
451
  }
452

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

460
    err = readInteger(size);
51✔
461
    if (err)
51✔
462
      return err;
10✔
463

464
    return readObject(variant, size, filter, nestingLimit);
41✔
465
  }
466

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

473
    if (nestingLimit.reached())
180✔
474
      return DeserializationError::TooDeep;
7✔
475

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

484
    for (; n; --n) {
422✔
485
      err = readKey();
289✔
486
      if (err)
289✔
487
        return err;
40✔
488

489
      JsonString key = _stringStorage.str();
265✔
490
      TFilter memberFilter = filter[key.c_str()];
265✔
491
      VariantData* member;
492

493
      if (memberFilter.allow()) {
265✔
494
        ARDUINOJSON_ASSERT(object != 0);
495

496
        // Save key in memory pool.
497
        key = _stringStorage.save();
198✔
498

499
        VariantSlot* slot = _pool->allocVariant();
198✔
500
        if (!slot)
198✔
501
          return DeserializationError::NoMemory;
×
502

503
        slot->setKey(key);
198✔
504
        object->add(slot);
198✔
505

506
        member = slot->data();
198✔
507
      } else {
508
        member = 0;
67✔
509
      }
510

511
      err = parseVariant(member, memberFilter, nestingLimit.decrement());
265✔
512
      if (err)
265✔
513
        return err;
16✔
514
    }
515

516
    return DeserializationError::Ok;
133✔
517
  }
518

519
  DeserializationError::Code readKey() {
289✔
520
    DeserializationError::Code err;
521
    uint8_t code;
522

523
    err = readByte(code);
289✔
524
    if (err)
289✔
525
      return err;
4✔
526

527
    if ((code & 0xe0) == 0xa0)
285✔
528
      return readString(code & 0x1f);
272✔
529

530
    switch (code) {
13✔
531
      case 0xd9:
8✔
532
        return readString<uint8_t>();
8✔
533

534
      case 0xda:
2✔
535
        return readString<uint16_t>();
2✔
536

537
      case 0xdb:
2✔
538
        return readString<uint32_t>();
2✔
539

540
      default:
1✔
541
        return DeserializationError::InvalidInput;
1✔
542
    }
543
  }
544

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

550
    err = readInteger(size);
23✔
551
    if (err)
23✔
552
      return err;
8✔
553

554
    return skipBytes(size + 1U);
15✔
555
  }
556

557
  MemoryPool* _pool;
558
  TReader _reader;
559
  TStringStorage _stringStorage;
560
  bool _foundSomething;
561
};
562

563
ARDUINOJSON_END_PRIVATE_NAMESPACE
564

565
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
566

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

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

585
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