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

bblanchon / ArduinoJson / 5371678521

pending completion
5371678521

push

github

bblanchon
Manage resources in `CollectionData`

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

3383 of 3405 relevant lines covered (99.35%)

6273.07 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/ResourceManager.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(ResourceManager* resources, TReader reader)
466✔
20
      : resources_(resources),
21
        reader_(reader),
22
        stringBuilder_(resources),
23
        foundSomething_(false) {}
466✔
24

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

33
 private:
34
  template <typename TFilter>
35
  DeserializationError::Code parseVariant(
818✔
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?
818✔
41
    err = readByte(code);
818✔
42
    if (err)
818✔
43
      return err;
11✔
44

45
    foundSomething_ = true;
807✔
46

47
    bool allowValue = filter.allowValue();
807✔
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) {
807✔
55
      case 0xc0:
5✔
56
        // already null
57
        return DeserializationError::Ok;
5✔
58

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

260
    fixEndianess(value);
173✔
261

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

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

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

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

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

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

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

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

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

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

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

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

308
    return DeserializationError::Ok;
8✔
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) {
34✔
332
    DeserializationError::Code err;
333
    T size;
334

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

430
    TFilter elementFilter = filter[0U];
68✔
431

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

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

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

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

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

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

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

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

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

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

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

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

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

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

498
        member = object->addMember(savedKey, resources_);
198✔
499
        if (!member)
198✔
500
          return DeserializationError::NoMemory;
×
501
      } else {
502
        member = 0;
67✔
503
      }
504

505
      err = parseVariant(member, memberFilter, nestingLimit.decrement());
265✔
506
      if (err)
265✔
507
        return err;
16✔
508
    }
509

510
    return DeserializationError::Ok;
133✔
511
  }
512

513
  DeserializationError::Code readKey() {
289✔
514
    DeserializationError::Code err;
515
    uint8_t code;
516

517
    err = readByte(code);
289✔
518
    if (err)
289✔
519
      return err;
4✔
520

521
    if ((code & 0xe0) == 0xa0)
285✔
522
      return readString(code & 0x1f);
272✔
523

524
    switch (code) {
13✔
525
      case 0xd9:
8✔
526
        return readString<uint8_t>();
8✔
527

528
      case 0xda:
2✔
529
        return readString<uint16_t>();
2✔
530

531
      case 0xdb:
2✔
532
        return readString<uint32_t>();
2✔
533

534
      default:
1✔
535
        return DeserializationError::InvalidInput;
1✔
536
    }
537
  }
538

539
  template <typename T>
540
  DeserializationError::Code skipExt() {
23✔
541
    DeserializationError::Code err;
542
    T size;
543

544
    err = readInteger(size);
23✔
545
    if (err)
23✔
546
      return err;
8✔
547

548
    return skipBytes(size + 1U);
15✔
549
  }
550

551
  ResourceManager* resources_;
552
  TReader reader_;
553
  StringBuilder stringBuilder_;
554
  bool foundSomething_;
555
};
556

557
ARDUINOJSON_END_PRIVATE_NAMESPACE
558

559
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
560

561
// Parses a MessagePack input and puts the result in a JsonDocument.
562
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
563
template <typename... Args>
564
DeserializationError deserializeMsgPack(JsonDocument& doc, Args&&... args) {
26✔
565
  using namespace detail;
566
  return deserialize<MsgPackDeserializer>(doc, detail::forward<Args>(args)...);
26✔
567
}
568

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

579
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