Coverage Report

Created: 2026-03-19 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/mcpack2pb/parser.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
// mcpack2pb - Make protobuf be front-end of mcpack/compack
19
20
// Date: Mon Oct 19 17:17:36 CST 2015
21
22
#include "mcpack2pb/parser.h"
23
24
namespace mcpack2pb {
25
26
// Binary head before fixed-size types.
27
class FieldFixedHead {
28
public:
29
    void set_type(uint8_t type) { _type = type; }
30
0
    uint8_t type() const { return _type; }
31
0
    size_t name_offset() const { return sizeof(FieldFixedHead); }
32
0
    size_t name_size() const { return _name_size; }
33
    void set_name_size(size_t name_size) { _name_size = name_size; }
34
0
    size_t value_offset() const { return name_offset() + name_size(); }
35
0
    size_t value_size() const { return (_type & FIELD_FIXED_MASK); }
36
0
    size_t full_size() const { return value_offset() + value_size(); }
37
private:
38
    uint8_t _type;  // FieldType
39
    uint8_t _name_size;
40
} __attribute__((__packed__));
41
42
// Binary head before string<=254 or raw<=255
43
class FieldShortHead {
44
public:
45
    void set_type(uint8_t type) { _type = type; }
46
0
    uint8_t type() const { return _type; }
47
0
    size_t name_offset() const { return sizeof(FieldShortHead); }
48
0
    size_t name_size() const { return _name_size; }
49
    void set_name_size(size_t name_size) { _name_size = name_size; }
50
0
    size_t value_offset() const { return name_offset() + name_size(); }
51
0
    size_t value_size() const { return _value_size; }
52
    void set_value_size(size_t value_size) { _value_size = value_size; }
53
0
    size_t full_size() const { return value_offset() + value_size(); }
54
private:
55
    uint8_t _type;
56
    uint8_t _name_size;
57
    uint8_t _value_size;
58
} __attribute__((__packed__));
59
60
// Binary head before variable-size fields.
61
class FieldLongHead {
62
public:
63
    void set_type(uint8_t type) { _type = type; }
64
0
    uint8_t type() const { return _type; }
65
0
    size_t name_offset() const { return sizeof(FieldLongHead); }
66
0
    size_t name_size() const { return _name_size; }
67
    void set_name_size(size_t name_size) { _name_size = name_size; }
68
0
    size_t value_offset() const { return name_offset() + name_size(); }
69
0
    size_t value_size() const { return _value_size; }
70
    void set_value_size(size_t value_size) { _value_size = value_size; }
71
0
    size_t full_size() const { return value_offset() + value_size(); }
72
private:
73
    uint8_t _type;
74
    uint8_t _name_size;
75
    uint32_t _value_size;
76
} __attribute__((__packed__));
77
78
// Assert type sizes:
79
BAIDU_CASSERT(sizeof(FieldFixedHead) == 2, size_assert);
80
BAIDU_CASSERT(sizeof(FieldShortHead) == 3, size_assert);
81
BAIDU_CASSERT(sizeof(FieldLongHead) == 6, size_assert);
82
BAIDU_CASSERT(sizeof(ItemsHead) == 4, size_assert);
83
BAIDU_CASSERT(sizeof(IsoItemsHead) == 1, size_assert);
84
85
0
void ObjectIterator::operator++() {
86
0
    if (_stream->popped_bytes() != _expected_popped_bytes) {
87
0
        if (_stream->popped_bytes() + _current_field.value.size() ==
88
0
            _expected_popped_bytes) {
89
            // skipping untouched values is acceptible.
90
0
            _stream->popn(_current_field.value.size());
91
0
        } else if (_stream->popped_bytes() < _expected_popped_bytes) {
92
0
            CHECK(false) << "value of name=" << _current_field.name
93
0
                         << " is not fully consumed, expected="
94
0
                         << _expected_popped_bytes << " actually="
95
0
                         << _stream->popped_bytes();
96
0
            return set_bad();
97
0
        } else {
98
0
            CHECK(false) << "Over popped in value of name=" << _current_field.name
99
0
                       << " expected=" << _expected_popped_bytes << " actually="
100
0
                       << _stream->popped_bytes();
101
0
            return set_bad();
102
0
        }
103
0
    }
104
0
    if (_expected_popped_bytes >= _expected_popped_end) {
105
0
        return set_end();
106
0
    }
107
0
    const uint8_t first_byte = _stream->peek1();
108
0
    if (first_byte & FIELD_FIXED_MASK) {
109
0
        FieldFixedHead head;
110
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldFixedHead) ||
111
0
            left_size() < head.full_size()) {
112
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
113
0
            return set_bad();
114
0
        }
115
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
116
0
            - sizeof(FieldFixedHead);
117
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
118
0
            _stream->popn(head.full_size() - sizeof(FieldFixedHead));
119
0
            return operator++();  // tailr
120
0
        }
121
0
        _current_field.name = _stream->ref_cut(&_name_backup_string, head.name_size());
122
0
        if (!_current_field.name.empty()) {
123
0
            _current_field.name.remove_suffix(1);
124
0
        }
125
0
        _current_field.value.set((FieldType)head.type(), _stream, head.value_size());
126
0
    } else if (first_byte & FIELD_SHORT_MASK) {
127
0
        FieldShortHead head;
128
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldShortHead) ||
129
0
            left_size() < head.full_size()) {
130
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
131
0
            return set_bad();
132
0
        }
133
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
134
0
            - sizeof(FieldShortHead);
135
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
136
            // Skip deleted field.
137
0
            _stream->popn(head.full_size() - sizeof(FieldShortHead));
138
0
            return operator++();  // tailr
139
0
        }
140
        // Remove FIELD_SHORT_MASK.
141
0
        FieldType type = (FieldType)(head.type() & ~FIELD_SHORT_MASK);
142
0
        _current_field.name = _stream->ref_cut(&_name_backup_string, head.name_size());
143
0
        if (!_current_field.name.empty()) {
144
0
            _current_field.name.remove_suffix(1);
145
0
        }
146
0
        _current_field.value.set(type, _stream, head.value_size());
147
0
    } else {
148
0
        FieldLongHead head;
149
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldLongHead) ||
150
0
            left_size() < head.full_size()) {
151
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
152
0
            return set_bad();
153
0
        }
154
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
155
0
            - sizeof(FieldLongHead);
156
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
157
            // Skip deleted field.
158
0
            _stream->popn(head.full_size() - sizeof(FieldLongHead));
159
0
            return operator++();  // tailr
160
0
        }
161
0
        _current_field.name = _stream->ref_cut(&_name_backup_string, head.name_size());
162
0
        if (!_current_field.name.empty()) {
163
0
            _current_field.name.remove_suffix(1);
164
0
        }
165
0
        _current_field.value.set((FieldType)head.type(), _stream, head.value_size());
166
0
    }
167
0
}
168
169
0
void ArrayIterator::operator++() {
170
0
    if (_stream->popped_bytes() != _expected_popped_bytes) {
171
0
        if (_stream->popped_bytes() + _current_field.size() ==
172
0
            _expected_popped_bytes) {
173
            // skipping untouched values is acceptible.
174
0
            _stream->popn(_current_field.size());
175
0
        } else if (_stream->popped_bytes() < _expected_popped_bytes) {
176
0
            CHECK(false) << "previous value is not fully consumed, expected="
177
0
                         << _expected_popped_bytes << " actually="
178
0
                         << _stream->popped_bytes();
179
0
            return set_bad();
180
0
        } else {
181
0
            CHECK(false) << "Over popped in previous value, expected="
182
0
                       << _expected_popped_bytes << " actually="
183
0
                       << _stream->popped_bytes();
184
0
            return set_bad();
185
0
        }
186
0
    }
187
0
    if (_expected_popped_bytes >= _expected_popped_end) {
188
0
        return set_end();
189
0
    }
190
0
    const uint8_t first_byte = _stream->peek1();
191
0
    if (first_byte & FIELD_FIXED_MASK) {
192
0
        FieldFixedHead head;
193
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldFixedHead) ||
194
0
            left_size() < head.full_size()) {
195
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
196
0
            return set_bad();
197
0
        }
198
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
199
0
            - sizeof(FieldFixedHead);
200
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
201
            // Skip deleted fields.
202
0
            _stream->popn(head.full_size() - sizeof(FieldFixedHead));
203
0
            return operator++();  // tailr
204
0
        }
205
0
        const uint32_t name_size = head.name_size();
206
0
        if (name_size) {
207
0
            _stream->popn(name_size);
208
0
        }
209
0
        _current_field.set((FieldType)head.type(), _stream, head.value_size());
210
0
    } else if (first_byte & FIELD_SHORT_MASK) {
211
0
        FieldShortHead head;
212
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldShortHead) ||
213
0
            left_size() < head.full_size()) {
214
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
215
0
            return set_bad();
216
0
        }
217
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
218
0
            - sizeof(FieldShortHead);
219
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
220
            // Skip deleted field.
221
0
            _stream->popn(head.full_size() - sizeof(FieldShortHead));
222
0
            return operator++();  // tailr
223
0
        }
224
        // Remove FIELD_SHORT_MASK.
225
0
        const FieldType type = (FieldType)(head.type() & ~FIELD_SHORT_MASK);
226
0
        const uint32_t name_size = head.name_size();
227
0
        if (name_size) {
228
0
            _stream->popn(name_size);
229
0
        }
230
0
        _current_field.set(type, _stream, head.value_size());
231
0
    } else {
232
0
        FieldLongHead head;
233
0
        if (_stream->cut_packed_pod(&head) != sizeof(FieldLongHead) ||
234
0
            left_size() < head.full_size()) {
235
0
            CHECK(false) << "buffer(size=" << left_size() << ") is not enough";
236
0
            return set_bad();
237
0
        }
238
0
        _expected_popped_bytes = _stream->popped_bytes() + head.full_size()
239
0
            - sizeof(FieldLongHead);
240
0
        if (!(head.type() & FIELD_NON_DELETED_MASK)) {
241
            // Skip deleted field.
242
0
            _stream->popn(head.full_size() - sizeof(FieldLongHead));
243
0
            return operator++();  // tailr
244
0
        }
245
0
        const uint32_t name_size = head.name_size();
246
0
        if (name_size) {
247
0
            _stream->popn(name_size);
248
0
        }
249
0
        _current_field.set((FieldType)head.type(), _stream, head.value_size());
250
0
    }
251
0
}
252
253
0
size_t unbox(InputStream* stream) {
254
0
    FieldLongHead head;
255
0
    if (stream->cut_packed_pod(&head) != sizeof(FieldLongHead)) {
256
0
        CHECK(false) << "Input buffer is not enough";
257
0
        return 0;
258
0
    }
259
0
    if (head.type() != FIELD_OBJECT) {
260
0
        CHECK(false) << "type=" << type2str(head.type()) << " is not object";
261
0
        return 0;
262
0
    }
263
0
    if (!(head.type() & FIELD_NON_DELETED_MASK)) {
264
0
        CHECK(false) << "The item is deleted";
265
0
        return 0;
266
0
    }
267
0
    if (head.name_size() != 0) {
268
0
        CHECK(false) << "The object should not have name";
269
0
        return 0;
270
0
    }
271
0
    return head.value_size();
272
0
}
273
274
0
std::ostream& operator<<(std::ostream& os, const UnparsedValue& value) {
275
    // TODO(gejun): More info.
276
0
    return os << type2str(value.type());
277
0
}
278
279
// NOTE: following functions are too big to be inlined. Actually non-inlining
280
// them perform better in tests.
281
0
int64_t UnparsedValue::as_int64(const char* var) {
282
0
    switch ((PrimitiveFieldType)_type) {
283
0
    case PRIMITIVE_FIELD_INT8:
284
0
        return _stream->cut_packed_pod<int8_t>();
285
0
    case PRIMITIVE_FIELD_INT16:
286
0
        return _stream->cut_packed_pod<int16_t>();
287
0
    case PRIMITIVE_FIELD_INT32:
288
0
        return _stream->cut_packed_pod<int32_t>();
289
0
    case PRIMITIVE_FIELD_INT64:
290
0
        return _stream->cut_packed_pod<int64_t>();
291
0
    case PRIMITIVE_FIELD_UINT8:
292
0
        return _stream->cut_packed_pod<uint8_t>();
293
0
    case PRIMITIVE_FIELD_UINT16:
294
0
        return _stream->cut_packed_pod<uint16_t>();
295
0
    case PRIMITIVE_FIELD_UINT32:
296
0
        return _stream->cut_packed_pod<uint32_t>();
297
0
    case PRIMITIVE_FIELD_UINT64: {
298
0
        const uint64_t value = _stream->cut_packed_pod<uint64_t>();
299
0
        if (value <= (uint64_t)std::numeric_limits<int64_t>::max()) {
300
0
            return (int64_t)value;
301
0
        }
302
0
        CHECK(false) << "uint64=" << value << " to " << var << " overflows";
303
0
        _stream->set_bad();
304
0
        return std::numeric_limits<int64_t>::max();
305
0
    }
306
0
    case PRIMITIVE_FIELD_BOOL:
307
0
        return _stream->cut_packed_pod<bool>();
308
0
    case PRIMITIVE_FIELD_FLOAT:
309
0
        CHECK(false) << "Can't set float=" << _stream->cut_packed_pod<float>()
310
0
                     << " to " << var;
311
0
        _stream->set_bad();
312
0
        return 0;
313
0
    case PRIMITIVE_FIELD_DOUBLE:
314
0
        CHECK(false) << "Can't set double=" << _stream->cut_packed_pod<double>()
315
0
                     << " to " << var;
316
0
        _stream->set_bad();
317
0
        return 0;
318
0
    }
319
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
320
0
    _stream->set_bad();
321
0
    return 0;
322
0
}
323
324
0
uint64_t UnparsedValue::as_uint64(const char* var) {
325
0
    switch ((PrimitiveFieldType)_type) {
326
0
    case PRIMITIVE_FIELD_INT8: {
327
0
        const int8_t value = _stream->cut_packed_pod<int8_t>();
328
0
        if (value >= 0) {
329
0
            return (uint64_t)value;
330
0
        }
331
0
        CHECK(false) << "Can't set int8=" << value << " to " << var;
332
0
        _stream->set_bad();
333
0
        return 0;
334
0
    }
335
0
    case PRIMITIVE_FIELD_INT16: {
336
0
        const int16_t value = _stream->cut_packed_pod<int16_t>();
337
0
        if (value >= 0) {
338
0
            return (uint64_t)value;
339
0
        }
340
0
        CHECK(false) << "Can't set int16=" << value << " to " << var;
341
0
        _stream->set_bad();
342
0
        return 0;
343
0
    }
344
0
    case PRIMITIVE_FIELD_INT32: {
345
0
        const int32_t value = _stream->cut_packed_pod<int32_t>();
346
0
        if (value >= 0) {
347
0
            return (uint64_t)value;
348
0
        }
349
0
        CHECK(false) << "Can't set int32=" << value << " to " << var;
350
0
        _stream->set_bad();
351
0
        return 0;
352
0
    }
353
0
    case PRIMITIVE_FIELD_INT64: {
354
0
        const int64_t value = _stream->cut_packed_pod<int64_t>();
355
0
        if (value >= 0) {
356
0
            return (uint64_t)value;
357
0
        }
358
0
        CHECK(false) << "Can't set int64=" << value << " to " << var;
359
0
        _stream->set_bad();
360
0
        return 0;
361
0
    }
362
0
    case PRIMITIVE_FIELD_UINT8:
363
0
        return _stream->cut_packed_pod<uint8_t>();
364
0
    case PRIMITIVE_FIELD_UINT16:
365
0
        return _stream->cut_packed_pod<uint16_t>();
366
0
    case PRIMITIVE_FIELD_UINT32:
367
0
        return _stream->cut_packed_pod<uint32_t>();
368
0
    case PRIMITIVE_FIELD_UINT64:
369
0
        return _stream->cut_packed_pod<uint64_t>();
370
0
    case PRIMITIVE_FIELD_BOOL:
371
0
        return _stream->cut_packed_pod<bool>();
372
0
    case PRIMITIVE_FIELD_FLOAT:
373
0
        CHECK(false) << "Can't set float=" << _stream->cut_packed_pod<float>()
374
0
                     << " to " << var;
375
0
        _stream->set_bad();
376
0
        return 0;
377
0
    case PRIMITIVE_FIELD_DOUBLE:
378
0
        CHECK(false) << "Can't set double=" << _stream->cut_packed_pod<double>()
379
0
                     << " to " << var;
380
0
        _stream->set_bad();
381
0
        return 0;
382
0
    }
383
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
384
0
    _stream->set_bad();
385
0
    return 0;
386
0
}
387
388
0
int32_t UnparsedValue::as_int32(const char* var) {
389
0
    switch ((PrimitiveFieldType)_type) {
390
0
    case PRIMITIVE_FIELD_INT8:
391
0
        return _stream->cut_packed_pod<int8_t>();
392
0
    case PRIMITIVE_FIELD_INT16:
393
0
        return _stream->cut_packed_pod<int16_t>();
394
0
    case PRIMITIVE_FIELD_INT32:
395
0
        return _stream->cut_packed_pod<int32_t>();
396
0
    case PRIMITIVE_FIELD_INT64: {
397
0
        const int64_t value = _stream->cut_packed_pod<int64_t>();
398
0
        if (value > std::numeric_limits<int32_t>::max()) {
399
0
            CHECK(false) << "int64=" << value << " to " << var << " overflows";
400
0
            _stream->set_bad();
401
0
            return std::numeric_limits<int32_t>::max();
402
0
        } else if (value < std::numeric_limits<int32_t>::min()) {
403
0
            CHECK(false) << "int64=" << value << " to " << var << " underflows";
404
0
            _stream->set_bad();
405
0
            return std::numeric_limits<int32_t>::min();
406
0
        }
407
0
        return (int32_t)value;
408
0
    }
409
0
    case PRIMITIVE_FIELD_UINT8:
410
0
        return _stream->cut_packed_pod<uint8_t>();
411
0
    case PRIMITIVE_FIELD_UINT16:
412
0
        return _stream->cut_packed_pod<uint16_t>();
413
0
    case PRIMITIVE_FIELD_UINT32: {
414
0
        const uint32_t value = _stream->cut_packed_pod<uint32_t>();
415
0
        if (value <= (uint32_t)std::numeric_limits<int32_t>::max()) {
416
0
            return (int32_t)value;
417
0
        }
418
0
        CHECK(false) << "uint32=" << value << " to " << var << " overflows";
419
0
        _stream->set_bad();
420
0
        return std::numeric_limits<int32_t>::max();
421
0
    }
422
0
    case PRIMITIVE_FIELD_UINT64: {
423
0
        const uint64_t value = _stream->cut_packed_pod<uint64_t>();
424
0
        if (value <= (uint64_t)std::numeric_limits<int32_t>::max()) {
425
0
            return (int32_t)value;
426
0
        }
427
0
        CHECK(false) << "uint64=" << value << " to " << var << " overflows";
428
0
        _stream->set_bad();
429
0
        return std::numeric_limits<int32_t>::max();
430
0
    }
431
0
    case PRIMITIVE_FIELD_BOOL:
432
0
        return _stream->cut_packed_pod<bool>();
433
0
    case PRIMITIVE_FIELD_FLOAT:
434
0
        CHECK(false) << "Can't set float=" << _stream->cut_packed_pod<float>()
435
0
                     << " to " << var;
436
0
        _stream->set_bad();
437
0
        return 0;
438
0
    case PRIMITIVE_FIELD_DOUBLE:
439
0
        CHECK(false) << "Can't set double=" << _stream->cut_packed_pod<double>()
440
0
                     << " to " << var;
441
0
        _stream->set_bad();
442
0
        return 0;
443
0
    }
444
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
445
0
    _stream->set_bad();
446
0
    return 0;
447
0
}
448
449
0
uint32_t UnparsedValue::as_uint32(const char* var) {
450
0
    switch ((PrimitiveFieldType)_type) {
451
0
    case PRIMITIVE_FIELD_INT8: {
452
0
        const int8_t value = _stream->cut_packed_pod<int8_t>();
453
0
        if (value >= 0) {
454
0
            return (uint32_t)value;
455
0
        }
456
0
        CHECK(false) << "Can't set int8=" << value << " to " << var;
457
0
        _stream->set_bad();
458
0
        return 0;
459
0
    }
460
0
    case PRIMITIVE_FIELD_INT16: {
461
0
        const int16_t value = _stream->cut_packed_pod<int16_t>();
462
0
        if (value >= 0) {
463
0
            return (uint32_t)value;
464
0
        }
465
0
        CHECK(false) << "Can't set int16=" << value << " to " << var;
466
0
        _stream->set_bad();
467
0
        return 0;
468
0
    }
469
0
    case PRIMITIVE_FIELD_INT32: {
470
0
        const int32_t value = _stream->cut_packed_pod<int32_t>();
471
0
        if (value >= 0) {
472
0
            return (uint32_t)value;
473
0
        }
474
0
        CHECK(false) << "Can't set int32=" << value << " to " << var;
475
0
        _stream->set_bad();
476
0
        return 0;
477
0
    }
478
0
    case PRIMITIVE_FIELD_INT64: {
479
0
        const int64_t value = _stream->cut_packed_pod<int64_t>();
480
0
        if (value >= 0 &&
481
0
            value <= (int64_t)std::numeric_limits<uint32_t>::max()) {
482
0
            return (uint32_t)value;
483
0
        }
484
0
        CHECK(false) << "Can't set int64=" << value << " to " << var;
485
0
        _stream->set_bad();
486
0
        return 0;
487
0
    }
488
0
    case PRIMITIVE_FIELD_UINT8:
489
0
        return _stream->cut_packed_pod<uint8_t>();
490
0
    case PRIMITIVE_FIELD_UINT16:
491
0
        return _stream->cut_packed_pod<uint16_t>();
492
0
    case PRIMITIVE_FIELD_UINT32:
493
0
        return _stream->cut_packed_pod<uint32_t>();
494
0
    case PRIMITIVE_FIELD_UINT64: {
495
0
        const uint64_t value = _stream->cut_packed_pod<uint64_t>();
496
0
        if (value <= std::numeric_limits<uint32_t>::max()) {
497
0
            return (uint32_t)value;
498
0
        }
499
0
        CHECK(false) << "uint64=" << value << " to " << var << " overflows";
500
0
        _stream->set_bad();
501
0
        return std::numeric_limits<uint32_t>::max();
502
0
    }
503
0
    case PRIMITIVE_FIELD_BOOL:
504
0
        return _stream->cut_packed_pod<bool>();
505
0
    case PRIMITIVE_FIELD_FLOAT:
506
0
        CHECK(false) << "Can't set float=" << _stream->cut_packed_pod<float>()
507
0
                     << " to " << var;
508
0
        _stream->set_bad();
509
0
        return 0;
510
0
    case PRIMITIVE_FIELD_DOUBLE:
511
0
        CHECK(false) << "Can't set double=" << _stream->cut_packed_pod<double>()
512
0
                     << " to " << var;
513
0
        _stream->set_bad();
514
0
        return 0;
515
0
    }
516
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
517
0
    _stream->set_bad();
518
0
    return 0;
519
0
}
520
521
0
bool UnparsedValue::as_bool(const char* var) {
522
0
    switch ((PrimitiveFieldType)_type) {
523
0
    case PRIMITIVE_FIELD_INT8:
524
0
        return _stream->cut_packed_pod<int8_t>();
525
0
    case PRIMITIVE_FIELD_INT16:
526
0
        return _stream->cut_packed_pod<int16_t>();
527
0
    case PRIMITIVE_FIELD_INT32:
528
0
        return _stream->cut_packed_pod<int32_t>();
529
0
    case PRIMITIVE_FIELD_INT64:
530
0
        return _stream->cut_packed_pod<int64_t>();
531
0
    case PRIMITIVE_FIELD_UINT8:
532
0
        return _stream->cut_packed_pod<uint8_t>();
533
0
    case PRIMITIVE_FIELD_UINT16:
534
0
        return _stream->cut_packed_pod<uint16_t>();
535
0
    case PRIMITIVE_FIELD_UINT32:
536
0
        return _stream->cut_packed_pod<uint32_t>();
537
0
    case PRIMITIVE_FIELD_UINT64:
538
0
        return _stream->cut_packed_pod<uint64_t>();
539
0
    case PRIMITIVE_FIELD_BOOL:
540
0
        return _stream->cut_packed_pod<bool>();
541
0
    case PRIMITIVE_FIELD_FLOAT:
542
0
        CHECK(false) << "Can't set float=" << _stream->cut_packed_pod<float>()
543
0
                     << " to " << var;
544
0
        _stream->set_bad();
545
0
        return false;
546
0
    case PRIMITIVE_FIELD_DOUBLE:
547
0
        CHECK(false) << "Can't set double=" << _stream->cut_packed_pod<double>()
548
0
                     << " to " << var;
549
0
        _stream->set_bad();
550
0
        return false;
551
0
    }
552
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
553
0
    _stream->set_bad();
554
0
    return false;
555
0
}
556
557
0
float UnparsedValue::as_float(const char* var) {
558
0
    if (_type == FIELD_DOUBLE) {
559
0
        return (float)_stream->cut_packed_pod<double>();
560
0
    } else if (_type == FIELD_FLOAT) {
561
0
        return _stream->cut_packed_pod<float>();
562
0
    }
563
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
564
0
    _stream->set_bad();
565
0
    return 0;
566
0
}
567
568
0
double UnparsedValue::as_double(const char* var) {
569
0
    if (_type == FIELD_DOUBLE) {
570
0
        return _stream->cut_packed_pod<double>();
571
0
    } else if (_type == FIELD_FLOAT) {
572
0
        return _stream->cut_packed_pod<float>();
573
0
    }
574
0
    CHECK(false) << "Can't set type=" << type2str(_type) << " to " << var;
575
0
    _stream->set_bad();
576
0
    return 0;
577
0
}
578
579
0
void UnparsedValue::as_string(std::string* out, const char* var) {
580
0
    out->resize(_size - 1);
581
0
    if (_stream->cutn(&(*out)[0], _size - 1) != _size - 1) {
582
0
        CHECK(false) << "Not enough data for " << var;
583
0
        return;
584
0
    }
585
0
    _stream->popn(1);
586
0
}
587
588
0
std::string UnparsedValue::as_string(const char* var) {
589
0
    std::string result;
590
0
    as_string(&result, var);
591
0
    return result;
592
0
}
593
594
0
void UnparsedValue::as_binary(std::string* out, const char* var) {
595
0
    out->resize(_size);
596
0
    if (_stream->cutn(&(*out)[0], _size) != _size) {
597
0
        CHECK(false) << "Not enough data for " << var;
598
0
        return;
599
0
    }
600
0
}
601
602
0
std::string UnparsedValue::as_binary(const char* var) {
603
0
    std::string result;
604
0
    as_binary(&result, var);
605
0
    return result;
606
0
}
607
608
}  // namespace mcpack2pb