blob: 38db744b64461c2598d79b719ec89fda7e804489 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous08bbe112023-04-06 13:10:02 -07003#pragma once
Ed Tanous08bbe112023-04-06 13:10:02 -07004
Ed Tanousd7857202025-01-28 15:32:26 -08005#include "async_resp.hpp"
6#include "baserule.hpp"
7#include "http_request.hpp"
8#include "ruleparametertraits.hpp"
9
10#include <boost/callable_traits/args.hpp>
Ed Tanous08bbe112023-04-06 13:10:02 -070011
12#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080013#include <memory>
14#include <stdexcept>
Ed Tanous08bbe112023-04-06 13:10:02 -070015#include <string>
Ed Tanousd7857202025-01-28 15:32:26 -080016#include <tuple>
17#include <vector>
Ed Tanous08bbe112023-04-06 13:10:02 -070018
19namespace crow
20{
21namespace detail
22{
Ed Tanous08bbe112023-04-06 13:10:02 -070023
24template <typename Func, typename... ArgsWrapped>
25struct Wrapped
Ed Tanous1017ef82023-06-27 09:52:58 -070026{};
27
28template <typename Func, typename... ArgsWrapped>
29struct Wrapped<Func, std::tuple<ArgsWrapped...>>
Ed Tanous08bbe112023-04-06 13:10:02 -070030{
Ed Tanous1017ef82023-06-27 09:52:58 -070031 explicit Wrapped(Func f) : handler(std::move(f)) {}
Ed Tanous08bbe112023-04-06 13:10:02 -070032
Ed Tanouscfe3bc02023-06-26 12:47:24 -070033 std::function<void(ArgsWrapped...)> handler;
Ed Tanous08bbe112023-04-06 13:10:02 -070034
35 void operator()(const Request& req,
36 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
37 const std::vector<std::string>& params)
38 {
Ed Tanouscfe3bc02023-06-26 12:47:24 -070039 if constexpr (sizeof...(ArgsWrapped) == 2)
40 {
41 handler(req, asyncResp);
42 }
43 else if constexpr (sizeof...(ArgsWrapped) == 3)
44 {
45 handler(req, asyncResp, params[0]);
46 }
47 else if constexpr (sizeof...(ArgsWrapped) == 4)
48 {
49 handler(req, asyncResp, params[0], params[1]);
50 }
51 else if constexpr (sizeof...(ArgsWrapped) == 5)
52 {
53 handler(req, asyncResp, params[0], params[1], params[2]);
54 }
55 else if constexpr (sizeof...(ArgsWrapped) == 6)
56 {
57 handler(req, asyncResp, params[0], params[1], params[2], params[3]);
58 }
59 else if constexpr (sizeof...(ArgsWrapped) == 7)
60 {
61 handler(req, asyncResp, params[0], params[1], params[2], params[3],
62 params[4]);
63 }
Ed Tanous08bbe112023-04-06 13:10:02 -070064 }
65};
Ed Tanous08bbe112023-04-06 13:10:02 -070066} // namespace detail
67
68class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
69{
70 public:
71 explicit DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) {}
72
73 void validate() override
74 {
75 if (!erasedHandler)
76 {
77 throw std::runtime_error("no handler for url " + rule);
78 }
79 }
80
81 void handle(const Request& req,
82 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
83 const std::vector<std::string>& params) override
84 {
85 erasedHandler(req, asyncResp, params);
86 }
87
88 template <typename Func>
89 void operator()(Func f)
90 {
91 using boost::callable_traits::args_t;
Ed Tanous1017ef82023-06-27 09:52:58 -070092 erasedHandler = detail::Wrapped<Func, args_t<Func>>(std::move(f));
Ed Tanous08bbe112023-04-06 13:10:02 -070093 }
94
95 private:
96 std::function<void(const Request&,
97 const std::shared_ptr<bmcweb::AsyncResp>&,
98 const std::vector<std::string>&)>
99 erasedHandler;
100};
101
102} // namespace crow