1 //
2 // MessagePack for C++ deserializing routine
3 //
4 // Copyright (C) 2017 KONDO Takatoshi
5 //
6 //    Distributed under the Boost Software License, Version 1.0.
7 //    (See accompanying file LICENSE_1_0.txt or copy at
8 //    http://www.boost.org/LICENSE_1_0.txt)
9 //
10 #ifndef MSGPACK_V2_X3_PARSE_HPP
11 #define MSGPACK_V2_X3_PARSE_HPP
12 
13 #if defined(MSGPACK_USE_X3_PARSE)
14 
15 #include <boost/version.hpp>
16 
17 #if BOOST_VERSION >= 106100
18 
19 #include "msgpack/versioning.hpp"
20 #include "msgpack/x3_parse_decl.hpp"
21 
22 #if __GNUC__ >= 4
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wunused-parameter"
25 #endif // __GNUC__ >= 4
26 
27 #include <boost/config/warning_disable.hpp>
28 #include <boost/spirit/home/x3.hpp>
29 #include <boost/spirit/home/x3/binary.hpp>
30 
31 namespace msgpack {
32 
33 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v2)34 MSGPACK_API_VERSION_NAMESPACE(v2) {
35 /// @endcond
36 
37 namespace detail {
38 
39 namespace x3 = boost::spirit::x3;
40 
41 using x3::byte_;
42 
43 // byte range utility
44 const auto byte_range = [](const std::uint8_t from, const std::uint8_t to) {
45     const auto check = [from, to](auto& ctx)
46     {
47         const std::uint8_t value = x3::_attr(ctx);
48         x3::_val(ctx) = value;
49         x3::_pass(ctx) = from <= value && value <= to;
50     };
51     return x3::byte_ [check];
52 };
53 
54 // MessagePack rule
55 const auto mp_positive_fixint = byte_range(0x00, 0x7f);
56 const auto mp_fixmap          = byte_range(0x80, 0x8f);
57 const auto mp_fixarray        = byte_range(0x90, 0x9f);
58 const auto mp_fixstr          = byte_range(0xa0, 0xbf);
59 const auto mp_nil             = x3::byte_(0xc0);
60 const auto mp_false           = x3::byte_(0xc2);
61 const auto mp_true            = x3::byte_(0xc3);
62 const auto mp_bin8            = x3::byte_(0xc4);
63 const auto mp_bin16           = x3::byte_(0xc5);
64 const auto mp_bin32           = x3::byte_(0xc6);
65 const auto mp_ext8            = x3::byte_(0xc7);
66 const auto mp_ext16           = x3::byte_(0xc8);
67 const auto mp_ext32           = x3::byte_(0xc9);
68 const auto mp_float32         = x3::byte_(0xca);
69 const auto mp_float64         = x3::byte_(0xcb);
70 const auto mp_uint8           = x3::byte_(0xcc);
71 const auto mp_uint16          = x3::byte_(0xcd);
72 const auto mp_uint32          = x3::byte_(0xce);
73 const auto mp_uint64          = x3::byte_(0xcf);
74 const auto mp_int8            = x3::byte_(0xd0);
75 const auto mp_int16           = x3::byte_(0xd1);
76 const auto mp_int32           = x3::byte_(0xd2);
77 const auto mp_int64           = x3::byte_(0xd3);
78 const auto mp_fixext1         = x3::byte_(0xd4);
79 const auto mp_fixext2         = x3::byte_(0xd5);
80 const auto mp_fixext4         = x3::byte_(0xd6);
81 const auto mp_fixext8         = x3::byte_(0xd7);
82 const auto mp_fixext16        = x3::byte_(0xd8);
83 const auto mp_str8            = x3::byte_(0xd9);
84 const auto mp_str16           = x3::byte_(0xda);
85 const auto mp_str32           = x3::byte_(0xdb);
86 const auto mp_array16         = x3::byte_(0xdc);
87 const auto mp_array32         = x3::byte_(0xdd);
88 const auto mp_map16           = x3::byte_(0xde);
89 const auto mp_map32           = x3::byte_(0xdf);
90 const auto mp_negative_fixint = byte_range(0xe0, 0xff);
91 
92 const auto mp_d_uint8 = x3::byte_;
93 const auto mp_d_uint16 = x3::big_word;
94 const auto mp_d_uint32 = x3::big_dword;
95 const auto mp_d_uint64 = x3::big_qword;
96 
97 const auto mp_d_int8 = x3::byte_;
98 const auto mp_d_int16 = x3::big_word;
99 const auto mp_d_int32 = x3::big_dword;
100 const auto mp_d_int64 = x3::big_qword;
101 
102 x3::rule<class mp_object> const mp_object("mp_object");
103 x3::rule<class array_items> const array_item("array_item");
104 x3::rule<class map_items> const map_item("map_item");
105 x3::rule<class kv> const kv("kv");
106 
107 struct tag_app_specific {};
108 struct index_size {
109     enum struct type_t {
110         array,
111         map,
112         other
113     };
114     index_size(std::size_t size, type_t type = type_t::other):size(size), type(type) {}
115     std::size_t index = 0;
116     std::size_t size;
117     type_t type;
118 };
119 
120 template <typename Visitor>
121 struct app_specific {
122     template <typename Vis>
123     app_specific(Vis&& vis):vis(vis) {}
124     std::vector<index_size> index_sizes;
125     Visitor vis;
126 };
127 
128 template <typename Visitor>
129 app_specific<Visitor> make_app_specific(Visitor&& vis) {
130     return app_specific<Visitor>(std::forward<Visitor>(vis));
131 }
132 
133 const auto more   = [](auto &ctx) {
134     auto& app_specific = x3::get<tag_app_specific>(ctx).get();
135     _pass(ctx) = app_specific.index_sizes.back().index++ < app_specific.index_sizes.back().size;
136 };
137 
138 const auto done   = [](auto &ctx) {
139     auto& app_specific = x3::get<tag_app_specific>(ctx).get();
140     if (app_specific.index_sizes.back().index == app_specific.index_sizes.back().size + 1) {
141         _pass(ctx) = true;
142         switch (app_specific.index_sizes.back().type) {
143         case index_size::type_t::array:
144             app_specific.vis.end_array();
145             break;
146         case index_size::type_t::map:
147             app_specific.vis.end_map();
148             break;
149         case index_size::type_t::other:
150             break;
151         }
152         app_specific.index_sizes.pop_back();
153     }
154     else {
155         _pass(ctx) = false;
156     }
157 };
158 
159 const auto mp_object_def =
160     // -----------------------------------------------
161     mp_nil [
162         (
163             [](auto& ctx){
164                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
165                 app_specific.vis.visit_nil();
166             }
167         )
168     ]
169     |
170     // -----------------------------------------------
171     mp_true [
172         (
173             [](auto& ctx){
174                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
175                 app_specific.vis.visit_boolean(true);
176             }
177         )
178     ]
179     |
180     // -----------------------------------------------
181     mp_false [
182         (
183             [](auto& ctx){
184                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
185                 app_specific.vis.visit_boolean(false);
186             }
187         )
188     ]
189     |
190     // -----------------------------------------------
191     mp_positive_fixint [
192         (
193             [](auto& ctx){
194                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
195                 app_specific.vis.visit_positive_integer(_attr(ctx));
196             }
197         )
198     ]
199     |
200     // -----------------------------------------------
201     mp_negative_fixint [
202         (
203             [](auto& ctx){
204                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
205                 std::int8_t val = _attr(ctx);
206                 app_specific.vis.visit_negative_integer(val);
207             }
208         )
209     ]
210     |
211     // -----------------------------------------------
212     mp_uint8 >> mp_d_uint8 [
213         (
214             [](auto& ctx){
215                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
216                 app_specific.vis.visit_negative_integer(_attr(ctx));
217             }
218         )
219     ]
220     |
221     // -----------------------------------------------
222     mp_uint16 >> mp_d_uint16 [
223         (
224             [](auto& ctx){
225                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
226                 app_specific.vis.visit_positive_integer(_attr(ctx));
227             }
228         )
229     ]
230     |
231     // -----------------------------------------------
232     mp_uint32 >> mp_d_uint32 [
233         (
234             [](auto& ctx){
235                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
236                 app_specific.vis.visit_positive_integer(_attr(ctx));
237             }
238         )
239     ]
240     |
241     // -----------------------------------------------
242     mp_uint64 >> mp_d_uint64 [
243         (
244             [](auto& ctx){
245                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
246                 app_specific.vis.visit_positive_integer(_attr(ctx));
247             }
248         )
249     ]
250     |
251     // -----------------------------------------------
252     mp_int8 >> mp_d_int8 [
253         (
254             [](auto& ctx){
255                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
256                 std::int8_t val = _attr(ctx);
257                 app_specific.vis.visit_negative_integer(val);
258             }
259         )
260     ]
261     |
262     // -----------------------------------------------
263     mp_int16 >> mp_d_int16 [
264         (
265             [](auto& ctx){
266                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
267                 std::int16_t val = _attr(ctx);
268                 app_specific.vis.visit_negative_integer(val);
269             }
270         )
271     ]
272     |
273     // -----------------------------------------------
274     mp_int32 >> mp_d_int32 [
275         (
276             [](auto& ctx){
277                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
278                 std::int32_t val = _attr(ctx);
279                 app_specific.vis.visit_negative_integer(val);
280             }
281         )
282     ]
283     |
284     // -----------------------------------------------
285     mp_int64 >> mp_d_int64 [
286         (
287             [](auto& ctx){
288                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
289                 std::int64_t val = _attr(ctx);
290                 app_specific.vis.visit_negative_integer(val);
291             }
292         )
293     ]
294     |
295     // -----------------------------------------------
296     mp_float32 >> mp_d_uint32 [
297         (
298             [](auto& ctx){
299                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
300                 union { uint32_t i; float f; } mem = { _attr(ctx) };
301                 app_specific.vis.visit_float32(mem.f);
302             }
303         )
304     ]
305     |
306     // -----------------------------------------------
307     mp_float64 >> mp_d_uint64 [
308         (
309             [](auto& ctx){
310                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
311                 union { uint64_t i; double f; } mem = { _attr(ctx) };
312 #if defined(TARGET_OS_IPHONE)
313                 // ok
314 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
315                 // https://github.com/msgpack/msgpack-perl/pull/1
316                 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
317 #endif
318                 app_specific.vis.visit_float64(mem.f);
319             }
320         )
321     ]
322     |
323     // -----------------------------------------------
324     mp_fixstr [
325         (
326             [](auto& ctx){
327                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
328                 std::size_t size = _attr(ctx) & 0b00011111;
329                 app_specific.index_sizes.emplace_back(size);
330             }
331         )
332     ]
333     >>
334     x3::raw [
335         *(x3::eps [more] >> x3::char_)
336         >> x3::eps [done]
337     ][
338         (
339             [](auto& ctx){
340                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
341                 auto const& str = _attr(ctx);
342                 std::size_t size = std::distance(str.begin(), str.end());
343                 app_specific.vis.visit_str(size ? &str.front() : nullptr, size);
344             }
345         )
346     ]
347     |
348     // -----------------------------------------------
349     mp_str8 >> mp_d_uint8 [
350         (
351             [](auto& ctx){
352                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
353                 app_specific.index_sizes.emplace_back(_attr(ctx));
354             }
355         )
356     ]
357     >>
358     x3::raw [
359         *(x3::eps [more] >> x3::char_)
360         >> x3::eps [done]
361     ][
362         (
363             [](auto& ctx){
364                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
365                 auto const& str = _attr(ctx);
366                 std::size_t size = std::distance(str.begin(), str.end());
367                 app_specific.vis.visit_str(size ? &str.front() : nullptr, size);
368             }
369         )
370     ]
371     |
372     // -----------------------------------------------
373     mp_str16 >> mp_d_uint16 [
374         (
375             [](auto& ctx){
376                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
377                 app_specific.index_sizes.emplace_back(_attr(ctx));
378             }
379         )
380     ]
381     >>
382     x3::raw [
383         *(x3::eps [more] >> x3::char_)
384         >> x3::eps [done]
385     ][
386         (
387             [](auto& ctx){
388                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
389                 auto const& str = _attr(ctx);
390                 std::size_t size = std::distance(str.begin(), str.end());
391                 app_specific.vis.visit_str(size ? &str.front() : nullptr, size);
392             }
393         )
394     ]
395     |
396     // -----------------------------------------------
397     mp_str32 >> mp_d_uint32 [
398         (
399             [](auto& ctx){
400                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
401                 app_specific.index_sizes.emplace_back(_attr(ctx));
402             }
403         )
404     ]
405     >>
406     x3::raw [
407         *(x3::eps [more] >> x3::char_)
408         >> x3::eps [done]
409     ][
410         (
411             [](auto& ctx){
412                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
413                 auto const& str = _attr(ctx);
414                 std::size_t size = std::distance(str.begin(), str.end());
415                 app_specific.vis.visit_str(size ? &str.front() : nullptr, size);
416             }
417         )
418     ]
419     |
420     // -----------------------------------------------
421     mp_bin8 >> mp_d_uint8 [
422         (
423             [](auto& ctx){
424                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
425                 app_specific.index_sizes.emplace_back(_attr(ctx));
426             }
427         )
428     ]
429     >>
430     x3::raw [
431         *(x3::eps [more] >> x3::char_)
432         >> x3::eps [done]
433     ][
434         (
435             [](auto& ctx){
436                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
437                 auto const& bin = _attr(ctx);
438                 std::size_t size = std::distance(bin.begin(), bin.end());
439                 app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size);
440             }
441         )
442     ]
443     |
444     // -----------------------------------------------
445     mp_bin16 >> mp_d_uint16 [
446         (
447             [](auto& ctx){
448                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
449                 app_specific.index_sizes.emplace_back(_attr(ctx));
450             }
451         )
452     ]
453     >>
454     x3::raw [
455         *(x3::eps [more] >> x3::char_)
456         >> x3::eps [done]
457     ][
458         (
459             [](auto& ctx){
460                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
461                 auto const& bin = _attr(ctx);
462                 std::size_t size = std::distance(bin.begin(), bin.end());
463                 app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size);
464             }
465         )
466     ]
467     |
468     // -----------------------------------------------
469     mp_bin32 >> mp_d_uint32 [
470         (
471             [](auto& ctx){
472                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
473                 app_specific.index_sizes.emplace_back(_attr(ctx));
474             }
475         )
476     ]
477     >>
478     x3::raw [
479         *(x3::eps [more] >> x3::char_)
480         >> x3::eps [done]
481     ][
482         (
483             [](auto& ctx){
484                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
485                 auto const& bin = _attr(ctx);
486                 std::size_t size = std::distance(bin.begin(), bin.end());
487                 app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size);
488             }
489         )
490     ]
491     |
492     // -----------------------------------------------
493     mp_fixarray [
494         (
495             [](auto& ctx){
496                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
497                 std::size_t size = _attr(ctx) & 0b00001111;
498                 app_specific.index_sizes.emplace_back(size, index_size::type_t::array);
499                 app_specific.vis.start_array(size);
500             }
501         )
502     ]
503     >> *(x3::eps [more] >> array_item)
504     >> x3::eps [done]
505     |
506     // -----------------------------------------------
507     mp_array16 >> mp_d_uint16 [
508         (
509             [](auto& ctx){
510                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
511                 std::size_t size = _attr(ctx);
512                 app_specific.index_sizes.emplace_back(size, index_size::type_t::array);
513                 app_specific.vis.start_array(size);
514             }
515         )
516     ]
517     >> *(x3::eps [more] >> array_item)
518     >> x3::eps [done]
519     |
520     // -----------------------------------------------
521     mp_array32 >> mp_d_uint32 [
522         (
523             [](auto& ctx){
524                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
525                 std::size_t size = _attr(ctx);
526                 app_specific.index_sizes.emplace_back(size, index_size::type_t::array);
527                 app_specific.vis.start_array(size);
528             }
529         )
530     ]
531     >> *(x3::eps [more] >> array_item)
532     >> x3::eps [done]
533     |
534     // -----------------------------------------------
535     mp_fixmap [
536         (
537             [](auto& ctx){
538                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
539                 std::size_t size = _attr(ctx) & 0b00001111;
540                 app_specific.index_sizes.emplace_back(size, index_size::type_t::map);
541                 app_specific.vis.start_map(size);
542             }
543         )
544     ]
545     >> *(x3::eps [more] >> map_item)
546     >> x3::eps [done]
547     |
548     // -----------------------------------------------
549     mp_map16 >> mp_d_uint16 [
550         (
551             [](auto& ctx){
552                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
553                 std::size_t size = _attr(ctx);
554                 app_specific.index_sizes.emplace_back(size, index_size::type_t::map);
555                 app_specific.vis.start_map(size);
556             }
557         )
558     ]
559     >> *(x3::eps [more] >> map_item)
560     >> x3::eps [done]
561     |
562     // -----------------------------------------------
563     mp_map32 >> mp_d_uint32 [
564         (
565             [](auto& ctx){
566                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
567                 std::size_t size = _attr(ctx);
568                 app_specific.index_sizes.emplace_back(size, index_size::type_t::map);
569                 app_specific.vis.start_map(size);
570             }
571         )
572     ]
573     >> *(x3::eps [more] >> map_item)
574     >> x3::eps [done]
575     |
576     // -----------------------------------------------
577     mp_fixext1 [
578         (
579             [](auto& ctx){
580                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
581                 app_specific.index_sizes.emplace_back(1+1);
582             }
583         )
584     ]
585     >>
586     x3::raw [
587         *(x3::eps [more] >> x3::char_)
588         >> x3::eps [done]
589     ][
590         (
591             [](auto& ctx){
592                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
593                 auto const& ext = _attr(ctx);
594                 std::size_t size = std::distance(ext.begin(), ext.end());
595                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
596             }
597         )
598     ]
599     |
600     // -----------------------------------------------
601     mp_fixext2 [
602         (
603             [](auto& ctx){
604                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
605                 app_specific.index_sizes.emplace_back(2+1);
606             }
607         )
608     ]
609     >>
610     x3::raw [
611         *(x3::eps [more] >> x3::char_)
612         >> x3::eps [done]
613     ][
614         (
615             [](auto& ctx){
616                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
617                 auto const& ext = _attr(ctx);
618                 std::size_t size = std::distance(ext.begin(), ext.end());
619                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
620             }
621         )
622     ]
623     |
624     // -----------------------------------------------
625     mp_fixext4 [
626         (
627             [](auto& ctx){
628                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
629                 app_specific.index_sizes.emplace_back(4+1);
630             }
631         )
632     ]
633     >>
634     x3::raw [
635         *(x3::eps [more] >> x3::char_)
636         >> x3::eps [done]
637     ][
638         (
639             [](auto& ctx){
640                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
641                 auto const& ext = _attr(ctx);
642                 std::size_t size = std::distance(ext.begin(), ext.end());
643                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
644             }
645         )
646     ]
647     |
648     // -----------------------------------------------
649     mp_fixext8 [
650         (
651             [](auto& ctx){
652                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
653                 app_specific.index_sizes.emplace_back(8+1);
654             }
655         )
656     ]
657     >>
658     x3::raw [
659         *(x3::eps [more] >> x3::char_)
660         >> x3::eps [done]
661     ][
662         (
663             [](auto& ctx){
664                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
665                 auto const& ext = _attr(ctx);
666                 std::size_t size = std::distance(ext.begin(), ext.end());
667                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
668             }
669         )
670     ]
671     |
672     // -----------------------------------------------
673     mp_fixext16 [
674         (
675             [](auto& ctx){
676                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
677                 app_specific.index_sizes.emplace_back(16+1);
678             }
679         )
680     ]
681     >>
682     x3::raw [
683         *(x3::eps [more] >> x3::char_)
684         >> x3::eps [done]
685     ][
686         (
687             [](auto& ctx){
688                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
689                 auto const& ext = _attr(ctx);
690                 std::size_t size = std::distance(ext.begin(), ext.end());
691                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
692             }
693         )
694     ]
695     |
696     // -----------------------------------------------
697     mp_ext8 >> mp_d_uint8 [
698         (
699             [](auto& ctx){
700                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
701                 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
702             }
703         )
704     ]
705     >>
706     x3::raw [
707         *(x3::eps [more] >> x3::char_)
708         >> x3::eps [done]
709     ][
710         (
711             [](auto& ctx){
712                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
713                 auto const& ext = _attr(ctx);
714                 std::size_t size = std::distance(ext.begin(), ext.end());
715                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
716             }
717         )
718     ]
719     |
720     // -----------------------------------------------
721     mp_ext16 >> mp_d_uint16 [
722         (
723             [](auto& ctx){
724                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
725                 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
726             }
727         )
728     ]
729     >>
730     x3::raw [
731         *(x3::eps [more] >> x3::char_)
732         >> x3::eps [done]
733     ][
734         (
735             [](auto& ctx){
736                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
737                 auto const& ext = _attr(ctx);
738                 std::size_t size = std::distance(ext.begin(), ext.end());
739                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
740             }
741         )
742     ]
743     |
744     // -----------------------------------------------
745     mp_ext32 >> mp_d_uint32 [
746         (
747             [](auto& ctx){
748                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
749                 app_specific.index_sizes.emplace_back(_attr(ctx)+1);
750             }
751         )
752     ]
753     >>
754     x3::raw [
755         *(x3::eps [more] >> x3::char_)
756         >> x3::eps [done]
757     ][
758         (
759             [](auto& ctx){
760                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
761                 auto const& ext = _attr(ctx);
762                 std::size_t size = std::distance(ext.begin(), ext.end());
763                 app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size);
764             }
765         )
766     ];
767 
768 const auto array_item_def =
769     x3::eps[
770         (
771             [](auto& ctx){
772                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
773                 app_specific.vis.start_array_item();
774                 _pass(ctx) = true;
775             }
776         )
777     ]
778     >>
779     mp_object
780     >>
781     x3::eps[
782         (
783             [](auto& ctx){
784                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
785                 app_specific.vis.end_array_item();
786                 _pass(ctx) = true;
787             }
788         )
789     ];
790 
791 const auto map_item_def = kv;
792 const auto kv_def =
793     x3::eps[
794         (
795             [](auto& ctx){
796                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
797                 app_specific.vis.start_map_key();
798                 _pass(ctx) = true;
799             }
800         )
801     ]
802     >>
803     mp_object
804     >>
805     x3::eps[
806         (
807             [](auto& ctx){
808                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
809                 app_specific.vis.end_map_key();
810                 _pass(ctx) = true;
811             }
812         )
813     ]
814     >>
815     x3::eps[
816         (
817             [](auto& ctx){
818                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
819                 app_specific.vis.start_map_value();
820                 _pass(ctx) = true;
821             }
822         )
823     ]
824     >>
825     mp_object
826     >>
827     x3::eps[
828         (
829             [](auto& ctx){
830                 auto& app_specific = x3::get<tag_app_specific>(ctx).get();
831                 app_specific.vis.end_map_value();
832                 _pass(ctx) = true;
833             }
834         )
835     ];
836 
837 BOOST_SPIRIT_DEFINE(
838     mp_object, array_item, map_item, kv
839 );
840 
841 const auto rule = mp_object;
842 
843 } // namespace detail
844 
845 template <typename Iterator, typename Visitor>
846 inline bool parse(Iterator&& begin, Iterator&& end, Visitor&& vis) {
847     auto data = detail::make_app_specific(std::forward<Visitor>(vis));
848     return detail::x3::parse(
849         std::forward<Iterator>(begin),
850         std::forward<Iterator>(end),
851         detail::x3::with<detail::tag_app_specific>(std::ref(data))[detail::rule]
852     );
853 }
854 
855 /// @cond
856 }  // MSGPACK_API_VERSION_NAMESPACE(v2)
857 /// @endcond
858 
859 }  // namespace msgpack
860 
861 #if __GNUC__ >= 4
862 #pragma GCC diagnostic pop
863 #endif // __GNUC__ >= 4
864 
865 #else  // BOOST_VERSION >= 106100
866 
867 #error Boost 1.61.0 or later is required to use x3 parse
868 
869 #endif // BOOST_VERSION >= 106100
870 
871 #endif // defined(MSGPACK_USE_X3_PARSE)
872 
873 #endif // MSGPACK_V2_X3_PARSE_HPP
874