1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 #include "baserule.hpp" 5 #include "ruleparametertraits.hpp" 6 #include "websocket.hpp" 7 8 #include <boost/beast/http/verb.hpp> 9 10 #include <functional> 11 #include <limits> 12 #include <string> 13 #include <type_traits> 14 15 namespace crow 16 { 17 namespace detail 18 { 19 20 template <typename Func, typename... ArgsWrapped> 21 struct Wrapped 22 {}; 23 24 template <typename Func, typename... ArgsWrapped> 25 struct Wrapped<Func, std::tuple<ArgsWrapped...>> 26 { 27 explicit Wrapped(Func f) : handler(std::move(f)) {} 28 29 std::function<void(ArgsWrapped...)> handler; 30 31 void operator()(const Request& req, 32 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 33 const std::vector<std::string>& params) 34 { 35 if constexpr (sizeof...(ArgsWrapped) == 2) 36 { 37 handler(req, asyncResp); 38 } 39 else if constexpr (sizeof...(ArgsWrapped) == 3) 40 { 41 handler(req, asyncResp, params[0]); 42 } 43 else if constexpr (sizeof...(ArgsWrapped) == 4) 44 { 45 handler(req, asyncResp, params[0], params[1]); 46 } 47 else if constexpr (sizeof...(ArgsWrapped) == 5) 48 { 49 handler(req, asyncResp, params[0], params[1], params[2]); 50 } 51 else if constexpr (sizeof...(ArgsWrapped) == 6) 52 { 53 handler(req, asyncResp, params[0], params[1], params[2], params[3]); 54 } 55 else if constexpr (sizeof...(ArgsWrapped) == 7) 56 { 57 handler(req, asyncResp, params[0], params[1], params[2], params[3], 58 params[4]); 59 } 60 } 61 }; 62 } // namespace detail 63 64 class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> 65 { 66 public: 67 explicit DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) {} 68 69 void validate() override 70 { 71 if (!erasedHandler) 72 { 73 throw std::runtime_error("no handler for url " + rule); 74 } 75 } 76 77 void handle(const Request& req, 78 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 79 const std::vector<std::string>& params) override 80 { 81 erasedHandler(req, asyncResp, params); 82 } 83 84 template <typename Func> 85 void operator()(Func f) 86 { 87 using boost::callable_traits::args_t; 88 erasedHandler = detail::Wrapped<Func, args_t<Func>>(std::move(f)); 89 } 90 91 private: 92 std::function<void(const Request&, 93 const std::shared_ptr<bmcweb::AsyncResp>&, 94 const std::vector<std::string>&)> 95 erasedHandler; 96 }; 97 98 } // namespace crow 99