xref: /openbmc/bmcweb/redfish-core/include/redfishoemrule.hpp (revision fdf51f5c824273aafaa9262932735ca443db23eb)
1 #pragma once
2 #include "async_resp.hpp"
3 #include "sub_request.hpp"
4 
5 #include <nlohmann/json.hpp>
6 
7 #include <functional>
8 #include <memory>
9 #include <stdexcept>
10 #include <string>
11 #include <string_view>
12 #include <type_traits>
13 #include <vector>
14 
15 namespace redfish
16 {
17 class OemBaseRule
18 {
19   public:
OemBaseRule(std::string_view thisRule)20     explicit OemBaseRule(std::string_view thisRule) : rule(thisRule) {}
21     virtual ~OemBaseRule() = default;
22     OemBaseRule(const OemBaseRule&) = delete;
23     OemBaseRule(OemBaseRule&&) = delete;
24     OemBaseRule& operator=(const OemBaseRule&) = delete;
25     OemBaseRule& operator=(const OemBaseRule&&) = delete;
26 
27     virtual void handle(const SubRequest& req,
28                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
29                         const std::vector<std::string>& params) = 0;
30     std::string rule;
31 };
32 
33 template <typename... Args>
34 class OemRule : public OemBaseRule
35 {
36   public:
37     using self_t = OemRule<Args...>;
38 
OemRule(std::string_view ruleIn)39     explicit OemRule(std::string_view ruleIn) : OemBaseRule(ruleIn) {}
40 
validate()41     void validate()
42     {
43         if (!handler)
44         {
45             throw std::runtime_error(
46                 "no OEM fragment handler for the rule {}" + rule);
47         }
48     }
49 
50     template <typename Func>
operator ()(Func && f)51     void operator()(Func&& f)
52     {
53         static_assert(
54             std::is_invocable_v<Func, SubRequest,
55                                 std::shared_ptr<bmcweb::AsyncResp>&, Args...>,
56             "Handler type is mismatched with URL parameters");
57         static_assert(
58             std::is_same_v<
59                 void, std::invoke_result_t<Func, SubRequest,
60                                            std::shared_ptr<bmcweb::AsyncResp>&,
61                                            Args...>>,
62             "Handler function with response argument should have void return type");
63 
64         handler = std::forward<Func>(f);
65     }
66 
handle(const SubRequest & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::vector<std::string> & params)67     void handle(const SubRequest& req,
68                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
69                 const std::vector<std::string>& params) override
70     {
71         if constexpr (sizeof...(Args) == 0)
72         {
73             handler(req, asyncResp);
74         }
75         else if constexpr (sizeof...(Args) == 1)
76         {
77             handler(req, asyncResp, params[0]);
78         }
79         else if constexpr (sizeof...(Args) == 2)
80         {
81             handler(req, asyncResp, params[0], params[1]);
82         }
83         else if constexpr (sizeof...(Args) == 3)
84         {
85             handler(req, asyncResp, params[0], params[1], params[2]);
86         }
87         else if constexpr (sizeof...(Args) == 4)
88         {
89             handler(req, asyncResp, params[0], params[1], params[2], params[3]);
90         }
91         else if constexpr (sizeof...(Args) == 5)
92         {
93             handler(req, asyncResp, params[0], params[1], params[2], params[3],
94                     params[4]);
95         }
96         static_assert(sizeof...(Args) <= 5, "More args than are supported");
97     }
98 
99   private:
100     std::function<void(const SubRequest&,
101                        const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>
102         handler;
103 };
104 } // namespace redfish
105