Coverage Report

Created: 2026-09-03 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp
Line
Count
Source
1
// Copyright 2013-2026 Daniel Parker
2
// Distributed under the Boost license, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5
// See https://github.com/danielaparker/jsoncons for latest version
6
7
#ifndef JSONCONS_EXT_MSGPACK_MSGPACK_ENCODER_HPP
8
#define JSONCONS_EXT_MSGPACK_MSGPACK_ENCODER_HPP
9
10
#include <cstddef>
11
#include <cstdint>
12
#include <cstdlib>
13
#include <limits> // std::numeric_limits
14
#include <memory>
15
#include <system_error>
16
#include <utility> // std::move
17
#include <vector>
18
19
#include <jsoncons/config/compiler_support.hpp>
20
#include <jsoncons/config/jsoncons_config.hpp>
21
#include <jsoncons/utility/read_number.hpp>
22
#include <jsoncons/json_exception.hpp>
23
#include <jsoncons/json_type.hpp>
24
#include <jsoncons/json_visitor.hpp>
25
#include <jsoncons/semantic_tag.hpp>
26
#include <jsoncons/ser_utils.hpp>
27
#include <jsoncons/sink.hpp>
28
#include <jsoncons/utility/bigint.hpp>
29
#include <jsoncons/utility/binary.hpp>
30
#include <jsoncons/utility/byte_string.hpp>
31
#include <jsoncons/utility/unicode_traits.hpp>
32
33
#include <jsoncons_ext/msgpack/msgpack_error.hpp>
34
#include <jsoncons_ext/msgpack/msgpack_options.hpp>
35
#include <jsoncons_ext/msgpack/msgpack_type.hpp>
36
37
namespace jsoncons { 
38
namespace msgpack {
39
40
    enum class msgpack_container_type {object, array};
41
42
    template <typename Sink=jsoncons::binary_stream_sink,typename Allocator=std::allocator<char>>
43
    class basic_msgpack_encoder final : public basic_json_visitor<char>
44
    {
45
        enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 };
46
47
        static constexpr int64_t nanos_in_milli = 1000000;
48
        static constexpr int64_t nanos_in_second = 1000000000;
49
        static constexpr int64_t millis_in_second = 1000;
50
    public:
51
        using allocator_type = Allocator;
52
        using char_type = char;
53
        using typename basic_json_visitor<char>::string_view_type;
54
        using sink_type = Sink;
55
56
    private:
57
        struct stack_item
58
        {
59
            msgpack_container_type type_;
60
            std::size_t length_;
61
            std::size_t index_{0};
62
63
            stack_item(msgpack_container_type type, std::size_t length = 0) noexcept
64
184k
               : type_(type), length_(length)
65
184k
            {
66
184k
            }
67
68
            std::size_t length() const
69
315k
            {
70
315k
                return length_;
71
315k
            }
72
73
            std::size_t count() const
74
315k
            {
75
315k
                return is_object() ? index_/2 : index_;
76
315k
            }
77
78
            bool is_object() const
79
315k
            {
80
315k
                return type_ == msgpack_container_type::object;
81
315k
            }
82
        };
83
84
        Sink sink_;
85
        int max_nesting_depth_;
86
        allocator_type alloc_;
87
88
        std::vector<stack_item> stack_;
89
        int nesting_depth_{0};
90
    public:
91
92
        // Noncopyable and nonmoveable
93
        basic_msgpack_encoder(const basic_msgpack_encoder&) = delete;
94
        basic_msgpack_encoder(basic_msgpack_encoder&&) = delete;
95
96
        explicit basic_msgpack_encoder(Sink&& sink, const Allocator& alloc = Allocator())
97
6.54k
           : basic_msgpack_encoder(std::forward<Sink>(sink), msgpack_encode_options(), alloc)
98
6.54k
        {
99
6.54k
        }
100
101
        explicit basic_msgpack_encoder(Sink&& sink, 
102
            const msgpack_encode_options& options, 
103
            const Allocator& alloc = Allocator())
104
6.54k
           : sink_(std::forward<Sink>(sink)),
105
6.54k
             max_nesting_depth_(options.max_nesting_depth()),
106
6.54k
             alloc_(alloc)
107
6.54k
        {
108
6.54k
        }
109
110
        ~basic_msgpack_encoder() noexcept
111
6.54k
        {
112
6.54k
            sink_.flush();
113
6.54k
        }
114
115
        basic_msgpack_encoder& operator=(const basic_msgpack_encoder&) = delete;
116
        basic_msgpack_encoder& operator=(basic_msgpack_encoder&&) = delete;
117
118
        void reset()
119
        {
120
            stack_.clear();
121
            nesting_depth_ = 0;
122
        }
123
124
        void reset(Sink&& sink)
125
        {
126
            sink_ = std::move(sink);
127
            reset();
128
        }
129
130
    private:
131
        // Implementing methods
132
133
        void visit_flush() final
134
1.60k
        {
135
1.60k
            sink_.flush();
136
1.60k
        }
137
138
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) final
139
0
        {
140
0
            ec = msgpack_errc::object_length_required;
141
0
            JSONCONS_VISITOR_RETURN;
142
0
        }
143
144
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) final
145
22.3k
        {
146
22.3k
            if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_))
147
0
            {
148
0
                ec = msgpack_errc::max_nesting_depth_exceeded;
149
0
                JSONCONS_VISITOR_RETURN;
150
0
            } 
151
22.3k
            stack_.emplace_back(msgpack_container_type::object, length);
152
153
22.3k
            if (length <= 15)
154
20.1k
            {
155
                // fixmap
156
20.1k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf));
157
20.1k
            }
158
2.19k
            else if (length <= 65535)
159
798
            {
160
                // map 16
161
798
                sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type);
162
798
                binary::native_to_big(static_cast<uint16_t>(length), 
163
798
                                      std::back_inserter(sink_));
164
798
            }
165
1.39k
            else if (length <= (std::numeric_limits<uint32_t>::max)())
166
1.39k
            {
167
                // map 32
168
1.39k
                sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type);
169
1.39k
                binary::native_to_big(static_cast<uint32_t>(length),
170
1.39k
                                      std::back_inserter(sink_));
171
1.39k
            }
172
173
22.3k
            JSONCONS_VISITOR_RETURN;
174
22.3k
        }
175
176
        JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context&, std::error_code& ec) final
177
13.4k
        {
178
13.4k
            JSONCONS_ASSERT(!stack_.empty());
179
13.4k
            --nesting_depth_;
180
181
13.4k
            if (stack_.back().count() < stack_.back().length())
182
417
            {
183
417
                ec = msgpack_errc::too_few_items;
184
417
                JSONCONS_VISITOR_RETURN;
185
417
            }
186
13.0k
            else if (stack_.back().count() > stack_.back().length())
187
0
            {
188
0
                ec = msgpack_errc::too_many_items;
189
0
                JSONCONS_VISITOR_RETURN;
190
0
            }
191
192
13.0k
            stack_.pop_back();
193
13.0k
            end_value();
194
13.0k
            JSONCONS_VISITOR_RETURN;
195
13.4k
        }
196
197
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) final
198
0
        {
199
0
            ec = msgpack_errc::array_length_required;
200
0
            JSONCONS_VISITOR_RETURN;
201
0
        }
202
203
        JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) final
204
162k
        {
205
162k
            if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_))
206
0
            {
207
0
                ec = msgpack_errc::max_nesting_depth_exceeded;
208
0
                JSONCONS_VISITOR_RETURN;
209
0
            } 
210
162k
            stack_.emplace_back(msgpack_container_type::array, length);
211
162k
            if (length <= 15)
212
157k
            {
213
                // fixarray
214
157k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf));
215
157k
            }
216
5.64k
            else if (length <= (std::numeric_limits<uint16_t>::max)())
217
2.07k
            {
218
                // array 16
219
2.07k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type);
220
2.07k
                binary::native_to_big(static_cast<uint16_t>(length),std::back_inserter(sink_));
221
2.07k
            }
222
3.57k
            else if (length <= (std::numeric_limits<uint32_t>::max)())
223
3.57k
            {
224
                // array 32
225
3.57k
                sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type);
226
3.57k
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
227
3.57k
            }
228
162k
            JSONCONS_VISITOR_RETURN;
229
162k
        }
230
231
        JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context&, std::error_code& ec) final
232
144k
        {
233
144k
            JSONCONS_ASSERT(!stack_.empty());
234
235
144k
            --nesting_depth_;
236
237
144k
            if (stack_.back().count() < stack_.back().length())
238
495
            {
239
495
                ec = msgpack_errc::too_few_items;
240
495
                JSONCONS_VISITOR_RETURN;
241
495
            }
242
144k
            else if (stack_.back().count() > stack_.back().length())
243
0
            {
244
0
                ec = msgpack_errc::too_many_items;
245
0
                JSONCONS_VISITOR_RETURN;
246
0
            }
247
248
144k
            stack_.pop_back();
249
144k
            end_value();
250
144k
            JSONCONS_VISITOR_RETURN;
251
144k
        }
252
253
        JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context& context, std::error_code& ec) final
254
633k
        {
255
633k
            visit_string(name, semantic_tag::none, context, ec);
256
633k
            JSONCONS_VISITOR_RETURN;
257
633k
        }
258
259
        JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag, const ser_context&, std::error_code&) final
260
11.3k
        {
261
            // nil
262
11.3k
            sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type);
263
11.3k
            end_value();
264
11.3k
            JSONCONS_VISITOR_RETURN;
265
11.3k
        }
266
267
        void write_timestamp(int64_t seconds, int64_t nanoseconds)
268
25.4k
        {
269
25.4k
            if ((seconds >> 34) == 0) 
270
17.5k
            {
271
17.5k
                uint64_t data64 = (nanoseconds << 34) | seconds;
272
17.5k
                if ((data64 & 0xffffffff00000000L) == 0) 
273
3.92k
                {
274
                    // timestamp 32
275
3.92k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
276
3.92k
                    sink_.push_back(0xff);
277
3.92k
                    binary::native_to_big(static_cast<uint32_t>(data64), std::back_inserter(sink_));
278
3.92k
                }
279
13.6k
                else 
280
13.6k
                {
281
                    // timestamp 64
282
13.6k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
283
13.6k
                    sink_.push_back(0xff);
284
13.6k
                    binary::native_to_big(static_cast<uint64_t>(data64), std::back_inserter(sink_));
285
13.6k
                }
286
17.5k
            }
287
7.87k
            else 
288
7.87k
            {
289
                // timestamp 96
290
7.87k
                sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
291
7.87k
                sink_.push_back(0x0c); // 12
292
7.87k
                sink_.push_back(0xff);
293
7.87k
                binary::native_to_big(static_cast<uint32_t>(nanoseconds), std::back_inserter(sink_));
294
7.87k
                binary::native_to_big(static_cast<uint64_t>(seconds), std::back_inserter(sink_));
295
7.87k
            }
296
25.4k
        }
297
298
        JSONCONS_VISITOR_RETURN_TYPE visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) final
299
663k
        {
300
663k
            switch (tag)
301
663k
            {
302
0
                case semantic_tag::epoch_second:
303
0
                {
304
0
                    int64_t seconds;
305
0
                    auto result = jsoncons::to_integer(sv.data(), sv.length(), seconds);
306
0
                    if (!result)
307
0
                    {
308
0
                        ec = msgpack_errc::invalid_timestamp;
309
0
                        JSONCONS_VISITOR_RETURN;
310
0
                    }
311
0
                    write_timestamp(seconds, 0);
312
0
                    break;
313
0
                }
314
0
                case semantic_tag::epoch_milli:
315
0
                {
316
0
                    bigint n;
317
0
                    auto result = to_bigint(sv.data(), sv.length(), n);
318
0
                    if (!result)
319
0
                    {
320
0
                        ec = msgpack_errc::invalid_timestamp;
321
0
                        JSONCONS_VISITOR_RETURN;
322
0
                    }
323
0
                    if (n != 0)
324
0
                    {
325
0
                        bigint q;
326
0
                        bigint rem;
327
0
                        n.divide(millis_in_second, q, rem, true);
328
0
                        auto seconds = static_cast<int64_t>(q);
329
0
                        auto nanoseconds = static_cast<int64_t>(rem) * nanos_in_milli;
330
0
                        if (nanoseconds < 0)
331
0
                        {
332
0
                            nanoseconds = -nanoseconds; 
333
0
                        }
334
0
                        write_timestamp(seconds, nanoseconds);
335
0
                    }
336
0
                    else
337
0
                    {
338
0
                        write_timestamp(0, 0);
339
0
                    }
340
0
                    break;
341
0
                }
342
24.0k
                case semantic_tag::epoch_nano:
343
24.0k
                {
344
24.0k
                    bigint n;
345
24.0k
                    auto result = to_bigint(sv.data(), sv.length(), n);
346
24.0k
                    if (!result)
347
0
                    {
348
0
                        ec = msgpack_errc::invalid_timestamp;
349
0
                        JSONCONS_VISITOR_RETURN;
350
0
                    }
351
24.0k
                    if (n != 0)
352
21.7k
                    {
353
21.7k
                        bigint q;
354
21.7k
                        bigint rem;
355
21.7k
                        n.divide(nanos_in_second, q, rem, true);
356
21.7k
                        auto seconds = static_cast<int64_t>(q);
357
21.7k
                        auto nanoseconds = static_cast<int64_t>(rem);
358
21.7k
                        if (nanoseconds < 0)
359
3.88k
                        {
360
3.88k
                            nanoseconds = -nanoseconds; 
361
3.88k
                        }
362
21.7k
                        write_timestamp(seconds, nanoseconds);
363
21.7k
                    }
364
2.26k
                    else
365
2.26k
                    {
366
2.26k
                        write_timestamp(0, 0);
367
2.26k
                    }
368
24.0k
                    break;
369
24.0k
                }
370
639k
                default:
371
639k
                {
372
639k
                    write_string_value(sv);
373
639k
                    end_value();
374
639k
                    break;
375
24.0k
                }
376
663k
            }
377
663k
            JSONCONS_VISITOR_RETURN;
378
663k
        }
379
380
        void write_string_value(const string_view_type& sv) 
381
639k
        {
382
639k
            auto sink = unicode_traits::validate(sv.data(), sv.size());
383
639k
            if (sink.ec != unicode_traits::unicode_errc())
384
0
            {
385
0
                JSONCONS_THROW(ser_error(msgpack_errc::invalid_utf8_text_string));
386
0
            }
387
388
639k
            const size_t length = sv.length();
389
639k
            if (length <= 31)
390
636k
            {
391
                // fixstr stores a byte array whose length is upto 31 bytes
392
636k
                sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast<uint8_t>(length));
393
636k
            }
394
2.71k
            else if (length <= (std::numeric_limits<uint8_t>::max)())
395
1.56k
            {
396
                // str 8 stores a byte array whose length is upto (2^8)-1 bytes
397
1.56k
                sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type);
398
1.56k
                sink_.push_back(static_cast<uint8_t>(length));
399
1.56k
            }
400
1.15k
            else if (length <= (std::numeric_limits<uint16_t>::max)())
401
754
            {
402
                // str 16 stores a byte array whose length is upto (2^16)-1 bytes
403
754
                sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type);
404
754
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
405
754
            }
406
398
            else if (length <= (std::numeric_limits<uint32_t>::max)())
407
398
            {
408
                // str 32 stores a byte array whose length is upto (2^32)-1 bytes
409
398
                sink_.push_back(jsoncons::msgpack::msgpack_type::str32_type);
410
398
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
411
398
            }
412
413
639k
            for (auto c : sv)
414
96.0M
            {
415
96.0M
                sink_.push_back(c);
416
96.0M
            }
417
639k
        }
418
419
        JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& b, 
420
            semantic_tag, 
421
            const ser_context&,
422
            std::error_code&) final
423
3.36k
        {
424
425
3.36k
            const std::size_t length = b.size();
426
3.36k
            if (length <= (std::numeric_limits<uint8_t>::max)())
427
2.56k
            {
428
                // bin 8 stores a byte array whose length is upto (2^8)-1 bytes
429
2.56k
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type);
430
2.56k
                sink_.push_back(static_cast<uint8_t>(length));
431
2.56k
            }
432
801
            else if (length <= (std::numeric_limits<uint16_t>::max)())
433
735
            {
434
                // bin 16 stores a byte array whose length is upto (2^16)-1 bytes
435
735
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type);
436
735
                binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
437
735
            }
438
66
            else if (length <= (std::numeric_limits<uint32_t>::max)())
439
66
            {
440
                // bin 32 stores a byte array whose length is upto (2^32)-1 bytes
441
66
                sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type);
442
66
                binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
443
66
            }
444
445
3.36k
            for (auto c : b)
446
6.64M
            {
447
6.64M
                sink_.push_back(c);
448
6.64M
            }
449
450
3.36k
            end_value();
451
3.36k
            JSONCONS_VISITOR_RETURN;
452
3.36k
        }
453
454
        JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& b, 
455
            uint64_t raw_tag, 
456
            const ser_context&,
457
            std::error_code&) final
458
550k
        {
459
550k
            const std::size_t length = b.size();
460
550k
            switch (length)
461
550k
            {
462
1.29k
                case 1:
463
1.29k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type);
464
1.29k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
465
1.29k
                    break;
466
534k
                case 2:
467
534k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type);
468
534k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
469
534k
                    break;
470
686
                case 4:
471
686
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
472
686
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
473
686
                    break;
474
4.13k
                case 8:
475
4.13k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
476
4.13k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
477
4.13k
                    break;
478
6.94k
                case 16:
479
6.94k
                    sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type);
480
6.94k
                    sink_.push_back(static_cast<uint8_t>(raw_tag));
481
6.94k
                    break;
482
2.67k
                default:
483
2.67k
                    if (length <= (std::numeric_limits<uint8_t>::max)())
484
1.66k
                    {
485
1.66k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
486
1.66k
                        sink_.push_back(static_cast<uint8_t>(length));
487
1.66k
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
488
1.66k
                    }
489
1.00k
                    else if (length <= (std::numeric_limits<uint16_t>::max)())
490
913
                    {
491
913
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext16_type);
492
913
                        binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
493
913
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
494
913
                    }
495
95
                    else if (length <= (std::numeric_limits<uint32_t>::max)())
496
95
                    {
497
95
                        sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type);
498
95
                        binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
499
95
                        sink_.push_back(static_cast<uint8_t>(raw_tag));
500
95
                    }
501
2.67k
                    break;
502
550k
            }
503
504
550k
            for (auto c : b)
505
11.0M
            {
506
11.0M
                sink_.push_back(c);
507
11.0M
            }
508
509
550k
            end_value();
510
550k
            JSONCONS_VISITOR_RETURN;
511
550k
        }
512
513
        JSONCONS_VISITOR_RETURN_TYPE visit_double(double val, 
514
            semantic_tag,
515
            const ser_context&,
516
            std::error_code&) final
517
76.5k
        {
518
76.5k
            float valf = (float)val;
519
76.5k
            if ((double)valf == val)
520
49.6k
            {
521
                // float 32
522
49.6k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type);
523
49.6k
                binary::native_to_big(valf,std::back_inserter(sink_));
524
49.6k
            }
525
26.8k
            else
526
26.8k
            {
527
                // float 64
528
26.8k
                sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type);
529
26.8k
                binary::native_to_big(val,std::back_inserter(sink_));
530
26.8k
            }
531
532
            // write double
533
534
76.5k
            end_value();
535
76.5k
            JSONCONS_VISITOR_RETURN;
536
76.5k
        }
537
538
        JSONCONS_VISITOR_RETURN_TYPE visit_int64(int64_t val, 
539
            semantic_tag tag, 
540
            const ser_context&,
541
            std::error_code&) final
542
220k
        {
543
220k
            switch (tag)
544
220k
            {
545
0
                case semantic_tag::epoch_second:
546
0
                    write_timestamp(val, 0);
547
0
                    break;
548
0
                case semantic_tag::epoch_milli:
549
0
                {
550
0
                    if (val != 0)
551
0
                    {
552
0
                        auto dv = std::div(val,millis_in_second);
553
0
                        int64_t seconds = dv.quot;
554
0
                        int64_t nanoseconds = dv.rem*nanos_in_milli;
555
0
                        if (nanoseconds < 0)
556
0
                        {
557
0
                            nanoseconds = -nanoseconds; 
558
0
                        }
559
0
                        write_timestamp(seconds, nanoseconds);
560
0
                    }
561
0
                    else
562
0
                    {
563
0
                        write_timestamp(0, 0);
564
0
                    }
565
0
                    break;
566
0
                }
567
0
                case semantic_tag::epoch_nano:
568
0
                {
569
0
                    if (val != 0)
570
0
                    {
571
0
                        auto dv = std::div(val,static_cast<int64_t>(nanos_in_second));
572
0
                        int64_t seconds = dv.quot;
573
0
                        int64_t nanoseconds = dv.rem;
574
0
                        if (nanoseconds < 0)
575
0
                        {
576
0
                            nanoseconds = -nanoseconds; 
577
0
                        }
578
0
                        write_timestamp(seconds, nanoseconds);
579
0
                    }
580
0
                    else
581
0
                    {
582
0
                        write_timestamp(0, 0);
583
0
                    }
584
0
                    break;
585
0
                }
586
220k
                default:
587
220k
                {
588
220k
                    if (val >= 0)
589
18.4k
                    {
590
18.4k
                        if (val <= 0x7f)
591
1.17k
                        {
592
                            // positive fixnum stores 7-bit positive integer
593
1.17k
                            sink_.push_back(static_cast<uint8_t>(val));
594
1.17k
                        }
595
17.2k
                        else if (val <= (std::numeric_limits<uint8_t>::max)())
596
600
                        {
597
                            // uint 8 stores a 8-bit unsigned integer
598
600
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
599
600
                            sink_.push_back(static_cast<uint8_t>(val));
600
600
                        }
601
16.6k
                        else if (val <= (std::numeric_limits<uint16_t>::max)())
602
483
                        {
603
                            // uint 16 stores a 16-bit big-endian unsigned integer
604
483
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
605
483
                            binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
606
483
                        }
607
16.1k
                        else if (val <= (std::numeric_limits<uint32_t>::max)())
608
352
                        {
609
                            // uint 32 stores a 32-bit big-endian unsigned integer
610
352
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
611
352
                            binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
612
352
                        }
613
15.8k
                        else if (val <= (std::numeric_limits<int64_t>::max)())
614
15.8k
                        {
615
                            // int 64 stores a 64-bit big-endian signed integer
616
15.8k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
617
15.8k
                            binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
618
15.8k
                        }
619
18.4k
                    }
620
201k
                    else
621
201k
                    {
622
201k
                        if (val >= -32)
623
136k
                        {
624
                            // negative fixnum stores 5-bit negative integer
625
136k
                            binary::native_to_big(static_cast<int8_t>(val), std::back_inserter(sink_));
626
136k
                        }
627
65.2k
                        else if (val >= (std::numeric_limits<int8_t>::lowest)())
628
43.3k
                        {
629
                            // int 8 stores a 8-bit signed integer
630
43.3k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type);
631
43.3k
                            binary::native_to_big(static_cast<int8_t>(val),std::back_inserter(sink_));
632
43.3k
                        }
633
21.9k
                        else if (val >= (std::numeric_limits<int16_t>::lowest)())
634
12.2k
                        {
635
                            // int 16 stores a 16-bit big-endian signed integer
636
12.2k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type);
637
12.2k
                            binary::native_to_big(static_cast<int16_t>(val),std::back_inserter(sink_));
638
12.2k
                        }
639
9.69k
                        else if (val >= (std::numeric_limits<int32_t>::lowest)())
640
6.44k
                        {
641
                            // int 32 stores a 32-bit big-endian signed integer
642
6.44k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type);
643
6.44k
                            binary::native_to_big(static_cast<int32_t>(val),std::back_inserter(sink_));
644
6.44k
                        }
645
3.24k
                        else if (val >= (std::numeric_limits<int64_t>::lowest)())
646
3.24k
                        {
647
                            // int 64 stores a 64-bit big-endian signed integer
648
3.24k
                            sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type);
649
3.24k
                            binary::native_to_big(static_cast<int64_t>(val),std::back_inserter(sink_));
650
3.24k
                        }
651
201k
                    }
652
220k
                }
653
220k
                break;
654
220k
            }
655
220k
            end_value();
656
220k
            JSONCONS_VISITOR_RETURN;
657
220k
        }
658
659
        JSONCONS_VISITOR_RETURN_TYPE visit_uint64(uint64_t val, 
660
            semantic_tag tag, 
661
            const ser_context&,
662
            std::error_code&) final
663
1.21M
        {
664
1.21M
            switch (tag)
665
1.21M
            {
666
1.43k
                case semantic_tag::epoch_second:
667
1.43k
                    write_timestamp(static_cast<int64_t>(val), 0);
668
1.43k
                    break;
669
0
                case semantic_tag::epoch_milli:
670
0
                {
671
0
                    if (val != 0)
672
0
                    {
673
0
                        auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(millis_in_second));
674
0
                        int64_t seconds = dv.quot;
675
0
                        int64_t nanoseconds = dv.rem*nanos_in_milli;
676
0
                        if (nanoseconds < 0)
677
0
                        {
678
0
                            nanoseconds = -nanoseconds; 
679
0
                        }
680
0
                        write_timestamp(seconds, nanoseconds);
681
0
                    }
682
0
                    else
683
0
                    {
684
0
                        write_timestamp(0, 0);
685
0
                    }
686
0
                    break;
687
0
                }
688
0
                case semantic_tag::epoch_nano:
689
0
                {
690
0
                    if (val != 0)
691
0
                    {
692
0
                        auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(nanos_in_second));
693
0
                        int64_t seconds = dv.quot;
694
0
                        int64_t nanoseconds = dv.rem;
695
0
                        if (nanoseconds < 0)
696
0
                        {
697
0
                            nanoseconds = -nanoseconds; 
698
0
                        }
699
0
                        write_timestamp(seconds, nanoseconds);
700
0
                    }
701
0
                    else
702
0
                    {
703
0
                        write_timestamp(0, 0);
704
0
                    }
705
0
                    break;
706
0
                }
707
1.20M
                default:
708
1.20M
                {
709
1.20M
                    if (val <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
710
1.18M
                    {
711
                        // positive fixnum stores 7-bit positive integer
712
1.18M
                        sink_.push_back(static_cast<uint8_t>(val));
713
1.18M
                    }
714
26.2k
                    else if (val <= (std::numeric_limits<uint8_t>::max)())
715
14.0k
                    {
716
                        // uint 8 stores a 8-bit unsigned integer
717
14.0k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
718
14.0k
                        sink_.push_back(static_cast<uint8_t>(val));
719
14.0k
                    }
720
12.2k
                    else if (val <= (std::numeric_limits<uint16_t>::max)())
721
862
                    {
722
                        // uint 16 stores a 16-bit big-endian unsigned integer
723
862
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
724
862
                        binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
725
862
                    }
726
11.3k
                    else if (val <= (std::numeric_limits<uint32_t>::max)())
727
8.47k
                    {
728
                        // uint 32 stores a 32-bit big-endian unsigned integer
729
8.47k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
730
8.47k
                        binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
731
8.47k
                    }
732
2.91k
                    else if (val <= (std::numeric_limits<uint64_t>::max)())
733
2.91k
                    {
734
                        // uint 64 stores a 64-bit big-endian unsigned integer
735
2.91k
                        sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
736
2.91k
                        binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
737
2.91k
                    }
738
1.20M
                    break;
739
0
                }
740
1.21M
            }
741
1.21M
            end_value();
742
1.21M
            JSONCONS_VISITOR_RETURN;
743
1.21M
        }
744
745
        JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) final
746
272k
        {
747
            // true and false
748
272k
            sink_.push_back(static_cast<uint8_t>(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type));
749
750
272k
            end_value();
751
272k
            JSONCONS_VISITOR_RETURN;
752
272k
        }
753
754
        void end_value()
755
3.14M
        {
756
3.14M
            if (!stack_.empty())
757
3.13M
            {
758
3.13M
                ++stack_.back().index_;
759
3.13M
            }
760
3.14M
        }
761
    };
762
763
    using msgpack_stream_encoder = basic_msgpack_encoder<jsoncons::binary_stream_sink>;
764
    using msgpack_bytes_encoder = basic_msgpack_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>;
765
766
} // namespace msgpack
767
} // namespace jsoncons
768
769
#endif // JSONCONS_EXT_MSGPACK_MSGPACK_ENCODER_HPP