7 #ifndef CPPWAMP_COROUNPACKER_HPP
8 #define CPPWAMP_COROUNPACKER_HPP
16 #include <boost/asio/spawn.hpp>
19 #include "internal/callee.hpp"
38 template <
typename TSlot,
typename... TArgs>
55 using Yield = boost::asio::yield_context;
58 void invoke(
Event&& event, internal::IntegerSequence<S...>)
const;
77 template <
typename... TArgs,
typename TSlot>
96 template <
typename TSlot,
typename... TArgs>
113 using Yield = boost::asio::yield_context;
116 void invoke(
Event&& event, internal::IntegerSequence<S...>)
const;
125 template <
typename TSlot,
typename... TArgs>
142 template <
typename... TArgs,
typename TSlot>
144 simpleCoroEvent(TSlot&& slot);
149 template <
typename... TArgs,
typename TSlot>
168 template <
typename TSlot,
typename... TArgs>
185 using Yield = boost::asio::yield_context;
188 void invoke(
Invocation&& inv, internal::IntegerSequence<S...>)
const;
205 template <
typename... TArgs,
typename TSlot>
207 unpackedCoroRpc(TSlot&& slot);
228 template <
typename TSlot,
typename TResult,
typename... TArgs>
248 using Yield = boost::asio::yield_context;
252 internal::IntegerSequence<S...>)
const;
256 internal::IntegerSequence<S...>)
const;
265 template <
typename TSlot,
typename TResult,
typename... TArgs>
283 template <
typename TResult,
typename... TArgs,
typename TSlot>
285 simpleCoroRpc(TSlot&& slot);
290 template <
typename TResult,
typename... TArgs,
typename TSlot>
305 struct UnpackCoroError :
public Error
307 UnpackCoroError() :
Error(
"wamp.error.invalid_argument") {}
318 template <
typename S,
typename... A>
320 : slot_(std::move(slot))
324 template <
typename S,
typename... A>
327 if (event.args().size() <
sizeof...(A))
329 std::ostringstream oss;
330 oss <<
"Expected " <<
sizeof...(A)
331 <<
" args, but only got " << event.args().size();
332 throw internal::UnpackCoroError().withArgs(oss.str());
337 using Seq =
typename internal::GenIntegerSequence<
sizeof...(A)>::type;
338 invoke(std::move(event), Seq());
342 template <
typename S,
typename... A>
343 template <
int ...Seq>
345 internal::IntegerSequence<Seq...>)
const
352 void operator()(Yield yield)
354 std::tuple<ValueTypeOf<A>...> args;
357 event.convertToTuple(args);
358 slot(std::move(event), std::get<Seq>(std::move(args))...,
361 catch (
const error::BadType&)
371 boost::asio::get_associated_executor(slot_, event.executor());
372 boost::asio::spawn(executor, Spawned{slot_, std::move(event)});
376 template <
typename... TArgs,
typename TSlot>
380 std::forward<TSlot>(slot));
389 template <
typename S,
typename... A>
391 : slot_(std::move(slot))
395 template <
typename S,
typename... A>
398 if (event.args().size() <
sizeof...(A))
400 std::ostringstream oss;
401 oss <<
"Expected " <<
sizeof...(A)
402 <<
" args, but only got " << event.args().size();
403 throw internal::UnpackCoroError().withArgs(oss.str());
408 using Seq =
typename internal::GenIntegerSequence<
sizeof...(A)>::type;
409 invoke(std::move(event), Seq());
413 template <
typename S,
typename... A>
414 template <
int ...Seq>
417 internal::IntegerSequence<Seq...>)
const
424 void operator()(Yield yield)
426 std::tuple<ValueTypeOf<A>...> args;
429 event.convertToTuple(args);
430 slot(std::get<Seq>(std::move(args))..., yield);
432 catch (
const error::BadType&)
442 boost::asio::get_associated_executor(slot_, event.executor());
443 boost::asio::spawn(executor, Spawned{slot_, std::move(event)});
447 template <
typename... TArgs,
typename TSlot>
448 SimpleCoroEventUnpacker<DecayedSlot<TSlot>, TArgs...>
449 simpleCoroEvent(TSlot&& slot)
452 std::forward<TSlot>(slot));
456 template <
typename... TArgs,
typename TSlot>
461 std::forward<TSlot>(slot));
470 template <
typename S,
typename... A>
472 : slot_(std::move(slot))
476 template <
typename S,
typename... A>
479 if (inv.args().size() <
sizeof...(A))
481 std::ostringstream oss;
482 oss <<
"Expected " <<
sizeof...(A)
483 <<
" args, but only got " << inv.args().size();
484 throw internal::UnpackCoroError().withArgs(oss.str());
489 using Seq =
typename internal::GenIntegerSequence<
sizeof...(A)>::type;
490 invoke(std::move(inv), Seq());
496 template <
typename S,
typename... A>
497 template <
int ...Seq>
500 internal::IntegerSequence<Seq...>)
const
507 calleePtr_(inv.callee_),
508 reqId_(inv.requestId()),
512 void operator()(Yield yield)
516 std::tuple<ValueTypeOf<A>...> args;
517 inv_.convertToTuple(args);
518 Outcome outcome = slot_(std::move(inv_),
519 std::get<Seq>(std::move(args))...,
522 switch (outcome.type())
529 safeYield(std::move(outcome).asResult());
533 safeYield(std::move(outcome).asError());
537 assert(
false &&
"Unexpected wamp::Outcome::Type enumerator");
543 safeYield(std::move(e));
545 catch (
const error::BadType& e)
553 void safeYield(Result&& result)
555 auto callee = calleePtr_.lock();
557 callee->safeYield(reqId_, std::move(result));
560 void safeYield(Error&& error)
562 auto callee = calleePtr_.lock();
564 callee->safeYield(reqId_, std::move(error));
568 std::weak_ptr<internal::Callee> calleePtr_;
574 boost::asio::get_associated_executor(slot_, inv.executor());
575 boost::asio::spawn(executor, Spawned{slot_, std::move(inv)});
579 template <
typename... TArgs,
typename TSlot>
580 CoroInvocationUnpacker<DecayedSlot<TSlot>, TArgs...>
581 unpackedCoroRpc(TSlot&& slot)
584 std::forward<TSlot>(slot) );
592 template <
typename S,
typename R,
typename... A>
594 : slot_(std::move(slot))
598 template <
typename S,
typename R,
typename... A>
602 if (inv.args().size() <
sizeof...(A))
604 std::ostringstream oss;
605 oss <<
"Expected " <<
sizeof...(A)
606 <<
" args, but only got " << inv.args().size();
607 throw internal::UnpackCoroError().withArgs(oss.str());
612 using Seq =
typename internal::GenIntegerSequence<
sizeof...(A)>::type;
614 invoke(IsVoidResult{}, std::move(inv), Seq());
620 template <
typename S,
typename R,
typename... A>
621 template <
int ...Seq>
630 void operator()(Yield yield)
634 std::tuple<ValueTypeOf<A>...> args;
635 inv.convertToTuple(args);
636 slot(std::get<Seq>(std::move(args))..., yield);
639 catch (
const Error& e)
643 catch (
const error::BadType& e)
652 boost::asio::get_associated_executor(slot_, inv.
executor());
653 boost::asio::spawn(executor, Spawned{slot_, std::move(inv)});
657 template <
typename S,
typename R,
typename... A>
658 template <
int ...Seq>
659 void SimpleCoroInvocationUnpacker<S,R,A...>::invoke(
660 FalseType, Invocation&& inv, internal::IntegerSequence<Seq...>)
const
667 void operator()(Yield yield)
671 std::tuple<ValueTypeOf<A>...> args;
672 inv.convertToTuple(args);
673 ResultType result = slot(std::get<Seq>(std::move(args))...,
675 inv.yield(Result().withArgs(std::move(result)));
677 catch (
const Error& e)
681 catch (
const error::BadType& e)
689 auto executor = inv.executor();
690 boost::asio::spawn(executor, Spawned{slot_, std::move(inv)});
694 template <
typename TResult,
typename... TArgs,
typename TSlot>
695 SimpleCoroInvocationUnpacker<DecayedSlot<TSlot>, TResult, TArgs...>
696 simpleCoroRpc(TSlot&& slot)
699 std::forward<TSlot>(slot) );
703 template <
typename TResult,
typename... TArgs,
typename TSlot>
708 std::forward<TSlot>(slot) );
713 #endif // CPPWAMP_COROUNPACKER_HPP