Viam C++ SDK current
Loading...
Searching...
No Matches
service_helper.hpp
1#pragma once
2
3#include <type_traits>
4
5#include <grpcpp/support/status.h>
6
7#include <viam/sdk/resource/resource_server_base.hpp>
8
9namespace viam {
10namespace sdk {
11
13 public:
14 ::grpc::Status fail(::grpc::StatusCode code, const char* message) const noexcept;
15
16 ::grpc::Status failNoRequest() const noexcept;
17
18 ::grpc::Status failNoResource(const std::string& name) const noexcept;
19
20 ::grpc::Status failStdException(const std::exception& xcp) const noexcept;
21
22 ::grpc::Status failUnknownException() const noexcept;
23
24 protected:
25 explicit ServiceHelperBase(const char* method) noexcept : method_{method} {}
26
27 private:
28 const char* method_;
29};
30
31template <typename ServiceType, typename RequestType>
33 public:
34 ServiceHelper(const char* method, ResourceServer* rs, RequestType* request) noexcept
35 : ServiceHelperBase{method}, rs_{rs}, request_{request} {};
36
37 template <typename Callable>
38 ::grpc::Status operator()(Callable&& callable) const noexcept try {
39 if (!request_) {
40 return failNoRequest();
41 }
42 const auto resource = rs_->resource_manager()->resource<ServiceType>(request_->name());
43 if (!resource) {
44 return failNoResource(request_->name());
45 }
46 return invoke_(std::forward<Callable>(callable), std::move(resource));
47 } catch (const std::exception& xcp) {
48 return failStdException(xcp);
49 } catch (...) {
50 return failUnknownException();
51 }
52
53 auto getExtra() const {
54 return request_->has_extra() ? from_proto(request_->extra()) : ProtoStruct{};
55 }
56
57 private:
58#if __cplusplus >= 201703L
59 template <typename Callable, typename... Args>
60 using is_void_result = std::is_void<std::invoke_result_t<Callable, Args...>>;
61#else
62 template <typename Callable, typename... Args>
63 using is_void_result = std::is_void<std::result_of_t<Callable(Args...)>>;
64#endif
65
66 // Implementation of `invoke_` for a Callable returning non-void,
67 // presumably an error return, which we return as a
68 // ::grpc::Status.
69 template <typename Callable,
70 typename ResourcePtrType,
71 std::enable_if_t<!is_void_result<Callable, ServiceHelper&, ResourcePtrType&&>::value,
72 bool> = true>
73 ::grpc::Status invoke_(Callable&& callable, ResourcePtrType&& resource) const {
74 return std::forward<Callable>(callable)(*this, std::forward<ResourcePtrType>(resource));
75 }
76
77 // Implementation of `invoke_` for a Callable returning void,
78 // which is therefore either non-failing or communicates errors by
79 // throwing exceptions. We return an OK status automatically.
80 template <typename Callable,
81 typename ResourcePtrType,
82 std::enable_if_t<is_void_result<Callable, ServiceHelper&, ResourcePtrType&&>::value,
83 bool> = true>
84 ::grpc::Status invoke_(Callable&& callable, ResourcePtrType&& resource) const {
85 std::forward<Callable>(callable)(*this, std::forward<ResourcePtrType>(resource));
86 return {};
87 }
88
89 ResourceServer* rs_;
90 RequestType* request_;
91};
92
93template <typename ServiceType, typename RequestType>
94auto make_service_helper(const char* method, ResourceServer* rs, RequestType* request) {
95 return ServiceHelper<ServiceType, RequestType>{method, rs, request};
96}
97
98} // namespace sdk
99} // namespace viam
Definition resource_server_base.hpp:8
Definition service_helper.hpp:12
Definition service_helper.hpp:32