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 */
|