1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
#pragma once
#ifndef RESPONSE_H_MVRZEKPX
#define RESPONSE_H_MVRZEKPX
#include "rpc/detail/log.h"
#include "rpc/detail/make_unique.h"
#include "rpc/msgpack.hpp"
#include "rpc/config.h"
namespace rpc {
namespace detail {
//! \brief Represents a response and creates a msgpack to be sent back
//! as per the msgpack-rpc spec.
class response {
public:
//! \brief Creates a response that represents a normal return value.
//! \param id The sequence id (as per protocol).
//! \param result The return value to store in the response.
//! \tparam T Any msgpack-able type.
//! \note If there is both an error and result in the response,
//! the result will be discarded while packing the data.
template <typename T> static response make_result(uint32_t id, T &&result);
//! \brief Creates a response that represents an error.
//! \param id The sequence id (as per protocol).
//! \param error The error value to store in the response.
//! \tparam T Any msgpack-able type.
template <typename T> static response make_error(uint32_t id, T &&error);
//! \brief Constructs a response from RPCLIB_MSGPACK::object (useful when
//! reading a response from a stream).
response(RPCLIB_MSGPACK::object_handle o);
//! \brief Gets the response data as a RPCLIB_MSGPACK::sbuffer.
RPCLIB_MSGPACK::sbuffer get_data() const;
//! \brief Moves the specified object_handle into the response
//! as a result.
//! \param r The result to capture.
void capture_result(RPCLIB_MSGPACK::object_handle &r);
//! \brief Moves the specified object_handle into the response as an error.
//! \param e The error to capture.
void capture_error(RPCLIB_MSGPACK::object_handle &e);
//! \brief Returns the call id/index used to identify which call
//! this response corresponds to.
uint32_t get_id() const;
//! \brief Returns the error object stored in the response. Can
//! be empty.
std::shared_ptr<RPCLIB_MSGPACK::object_handle> get_error() const;
//! \brief Returns the result stored in the response. Can be empty.
std::shared_ptr<RPCLIB_MSGPACK::object_handle> get_result() const;
//! \brief Gets an empty response which means "no response" (not to be
//! confused with void return, i.e. this means literally
//! "don't write the response to the socket")
static response empty();
//! \brief If true, this response is empty (\see empty())
bool is_empty() const;
//! \brief The type of a response, according to the msgpack-rpc spec
using response_type =
std::tuple<uint32_t, uint32_t, RPCLIB_MSGPACK::object, RPCLIB_MSGPACK::object>;
private:
//! \brief Default constructor for responses.
response();
uint32_t id_;
// I really wish to avoid shared_ptr here but at this point asio does not
// work with move-only handlers in post() and I need to capture responses
// in lambdas.
std::shared_ptr<RPCLIB_MSGPACK::object_handle> error_;
std::shared_ptr<RPCLIB_MSGPACK::object_handle> result_;
bool empty_;
RPCLIB_CREATE_LOG_CHANNEL(response)
};
template <typename T>
inline response response::make_result(uint32_t id, T &&result) {
auto z = rpc::detail::make_unique<RPCLIB_MSGPACK::zone>();
RPCLIB_MSGPACK::object o(std::forward<T>(result), *z);
response inst;
inst.id_ = id;
inst.result_ = std::make_shared<RPCLIB_MSGPACK::object_handle>(o, std::move(z));
return inst;
}
template <>
inline response
response::make_result(uint32_t id, std::unique_ptr<RPCLIB_MSGPACK::object_handle> &&r) {
response inst;
inst.id_ = id;
inst.result_ = std::move(r);
return inst;
}
template <typename T>
inline response response::make_error(uint32_t id, T &&error) {
auto z = rpc::detail::make_unique<RPCLIB_MSGPACK::zone>();
RPCLIB_MSGPACK::object o(std::forward<T>(error), *z);
response inst;
inst.id_ = id;
inst.error_ = std::make_shared<RPCLIB_MSGPACK::object_handle>(o, std::move(z));
return inst;
}
} /* detail */
} /* rpc */
#endif /* end of include guard: RESPONSE_H_MVRZEKPX */
|