userver: userver/ugrpc/server/result.hpp Source File
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/ugrpc/server/result.hpp
4/// @brief @copybrief ugrpc::server::Result
5
6#include <optional>
7#include <variant>
8
9#include <grpcpp/support/status.h>
10
11USERVER_NAMESPACE_BEGIN
12
13namespace ugrpc::server {
14
15/// @brief Result type for service handlers (non server-streaming)
16///
17/// Provides a way to return either Response or grpc::Status
18template <typename Response>
19class Result {
20public:
21 /// Construct instance from Response, imply success status
22 /*implicit*/ Result(Response&& response) : result_{std::move(response)} {}
23
24 /// Construct instance from grpc::Status, only error status allowed
25 /*implicit*/ Result(grpc::Status&& status) : result_{std::move(status)} {
26 UINVARIANT(!GetErrorStatus().ok(), "Only error status allowed");
27 }
28
29 /// Construct instance from grpc::Status, only error status allowed
30 /*implicit*/ Result(const grpc::Status& status) : result_{status} {
31 UINVARIANT(!GetErrorStatus().ok(), "Only error status allowed");
32 }
33
34 /// @cond
35 bool IsSuccess() const { return std::holds_alternative<Response>(result_); }
36
37 Response&& ExtractResponse() && {
38 UINVARIANT(IsSuccess(), "ExtractResponse allowed only in success state");
39 return std::get<Response>(std::move(result_));
40 }
41
42 const Response& GetResponse() const {
43 UINVARIANT(IsSuccess(), "GetResponse allowed only in success state");
44 return std::get<Response>(result_);
45 }
46
47 const grpc::Status& GetErrorStatus() const {
48 UINVARIANT(!IsSuccess(), "GetErrorStatus allowed only in error state");
49 return std::get<grpc::Status>(result_);
50 }
51 /// @endcond
52
53private:
54 std::variant<Response, grpc::Status> result_;
55};
56
57/// @brief Special result type for server-streaming service handlers
58template <typename Response>
59class StreamingResult final {
60public:
61 /// Construct instance from grpc::Status
62 /*implicit*/ StreamingResult(grpc::Status&& status) : status_{std::move(status)} {}
63
64 /// Construct instance from grpc::Status
65 /*implicit*/ StreamingResult(const grpc::Status& status) : status_{status} {}
66
67 /// Construct instance with last response
68 ///
69 /// Allows perform writing last response and coalesce it with status in a
70 /// single step.
71 /*implicit*/ StreamingResult(Response&& last_response) : last_response_(std::move(last_response)) {}
72
73 /// @cond
74 bool HasLastResponse() const { return last_response_.has_value(); }
75
76 Response&& ExtractLastResponse() && { return std::move(last_response_).value(); }
77
78 const Response& GetLastResponse() const { return last_response_.value(); }
79
80 const grpc::Status& GetStatus() const { return status_; }
81 /// @endcond
82
83private:
84 std::optional<Response> last_response_;
85 grpc::Status status_{grpc::Status::OK};
86};
87
88} // namespace ugrpc::server
89
90USERVER_NAMESPACE_END