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