JSON-RPC 2.0
JSON-RPC 2.0 Modern C++ Library
Loading...
Searching...
No Matches
typed_handlers.hpp
Go to the documentation of this file.
1#pragma once
2
24#include <expected>
25#include <optional>
26#include <utility>
27#include <variant>
28
29#include <asio/awaitable.hpp>
30#include <nlohmann/json.hpp>
31#include <spdlog/spdlog.h>
32
34
35namespace jsonrpc::endpoint {
36
37template <
38 typename ParamsType, typename ResultType,
39 typename ErrorType = std::monostate>
40 requires(FromJson<ParamsType> && ToJson<ResultType> && ToJson<ErrorType>)
42 private:
43 using SimpleHandler = std::function<asio::awaitable<ResultType>(ParamsType)>;
44 using ExpectedHandler =
45 std::function<asio::awaitable<std::expected<ResultType, ErrorType>>(
46 ParamsType)>;
47 using HandlerType = std::conditional_t<
48 std::is_same_v<ErrorType, std::monostate>, SimpleHandler,
49 ExpectedHandler>;
50
51 HandlerType handler_;
52
53 public:
54 // Constructor for non-error-aware handler
55 explicit TypedMethodHandler(SimpleHandler handler)
56 requires(std::is_same_v<ErrorType, std::monostate>)
57 : handler_(std::move(handler)) {
58 }
59
60 // Constructor for error-aware handler
61 explicit TypedMethodHandler(ExpectedHandler handler)
62 requires(!std::is_same_v<ErrorType, std::monostate>)
63 : handler_(std::move(handler)) {
64 }
65
66 auto operator()(std::optional<nlohmann::json> params)
67 -> asio::awaitable<nlohmann::json> {
68 ParamsType typed_params{};
69 try {
70 if (params.has_value()) {
71 typed_params = params.value().get<ParamsType>();
72 }
73 } catch (const nlohmann::json::exception& ex) {
74 throw std::runtime_error(
75 "Failed to parse parameters: " + std::string(ex.what()));
76 }
77
78 if constexpr (std::is_same_v<ErrorType, std::monostate>) {
79 if constexpr (std::is_void_v<ResultType>) {
80 co_await handler_(typed_params);
81 co_return nlohmann::json();
82 } else {
83 ResultType result = co_await handler_(typed_params);
84 co_return nlohmann::json(result);
85 }
86 } else {
87 auto result = co_await handler_(typed_params);
88 if (result) {
89 if constexpr (std::is_void_v<ResultType>) {
90 co_return nlohmann::json();
91 } else {
92 co_return nlohmann::json(*result);
93 }
94 } else {
95 throw result.error();
96 }
97 }
98 }
99};
100
101template <typename ParamsType, typename ErrorType = std::monostate>
102 requires(FromJson<ParamsType> && HasMessageMethod<ErrorType>)
104 private:
105 using SimpleHandler = std::function<asio::awaitable<void>(ParamsType)>;
106 using ExpectedHandler =
107 std::function<asio::awaitable<std::expected<void, ErrorType>>(
108 ParamsType)>;
109 using HandlerType = std::conditional_t<
110 std::is_same_v<ErrorType, std::monostate>, SimpleHandler,
111 ExpectedHandler>;
112
113 HandlerType handler_;
114
115 public:
116 explicit TypedNotificationHandler(SimpleHandler handler)
117 requires(std::is_same_v<ErrorType, std::monostate>)
118 : handler_(std::move(handler)) {
119 }
120
121 explicit TypedNotificationHandler(ExpectedHandler handler)
122 requires(!std::is_same_v<ErrorType, std::monostate>)
123 : handler_(std::move(handler)) {
124 }
125
126 auto operator()(std::optional<nlohmann::json> params)
127 -> asio::awaitable<void> {
128 ParamsType typed_params{};
129 try {
130 if (params.has_value()) {
131 typed_params = params.value().get<ParamsType>();
132 }
133 } catch (const nlohmann::json::exception& ex) {
134 spdlog::error("Failed to parse parameters: {}", ex.what());
135 co_return;
136 }
137
138 if constexpr (std::is_same_v<ErrorType, std::monostate>) {
139 co_await handler_(typed_params);
140 } else {
141 auto result = co_await handler_(typed_params);
142 if (!result) {
143 spdlog::warn(
144 "TypedNotificationHandler ignored error: {}",
145 result.error().Message());
146 }
147 }
148 }
149};
150
151} // namespace jsonrpc::endpoint
auto operator()(std::optional< nlohmann::json > params) -> asio::awaitable< nlohmann::json >
TypedMethodHandler(SimpleHandler handler)
TypedMethodHandler(ExpectedHandler handler)
auto operator()(std::optional< nlohmann::json > params) -> asio::awaitable< void >