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