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 template <typename Callable, typename... Args>
59 using is_void_result = std::is_void<std::result_of_t<Callable(Args...)>>;
60
61 // Implementation of `invoke_` for a Callable returning non-void,
62 // presumably an error return, which we return as a
63 // ::grpc::Status.
64 template <typename Callable,
65 typename ResourcePtrType,
66 std::enable_if_t<!is_void_result<Callable, ServiceHelper&, ResourcePtrType&&>::value,
67 bool> = true>
68 ::grpc::Status invoke_(Callable&& callable, ResourcePtrType&& resource) const {
69 return std::forward<Callable>(callable)(*this, std::forward<ResourcePtrType>(resource));
70 }
71
72 // Implementation of `invoke_` for a Callable returning void,
73 // which is therefore either non-failing or communicates errors by
74 // throwing exceptions. We return an OK status automatically.
75 template <typename Callable,
76 typename ResourcePtrType,
77 std::enable_if_t<is_void_result<Callable, ServiceHelper&, ResourcePtrType&&>::value,
78 bool> = true>
79 ::grpc::Status invoke_(Callable&& callable, ResourcePtrType&& resource) const {
80 std::forward<Callable>(callable)(*this, std::forward<ResourcePtrType>(resource));
81 return {};
82 }
83
84 ResourceServer* rs_;
85 RequestType* request_;
86};
87
88template <typename ServiceType, typename RequestType>
89auto make_service_helper(const char* method, ResourceServer* rs, RequestType* request) {
90 return ServiceHelper<ServiceType, RequestType>{method, rs, request};
91}
92
93} // namespace sdk
94} // namespace viam
Definition resource_server_base.hpp:8
Definition service_helper.hpp:12
Definition service_helper.hpp:32