1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 5 #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> 11 12 #include <functional> 13 #include <memory> 14 #include <stdexcept> 15 #include <string> 16 #include <tuple> 17 #include <vector> 18 19 namespace crow 20 { 21 namespace detail 22 { 23 24 template <typename Func, typename... ArgsWrapped> 25 struct Wrapped 26 {}; 27 28 template <typename Func, typename... ArgsWrapped> 29 struct Wrapped<Func, std::tuple<ArgsWrapped...>> 30 { Wrappedcrow::detail::Wrapped31 explicit Wrapped(Func f) : handler(std::move(f)) {} 32 33 std::function<void(ArgsWrapped...)> handler; 34 operator ()crow::detail::Wrapped35 void operator()(const Request& req, 36 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 37 const std::vector<std::string>& params) 38 { 39 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 } 64 } 65 }; 66 } // namespace detail 67 68 class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> 69 { 70 public: DynamicRule(const std::string & ruleIn)71 explicit DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) {} 72 validate()73 void validate() override 74 { 75 if (!erasedHandler) 76 { 77 throw std::runtime_error("no handler for url " + rule); 78 } 79 } 80 handle(const Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::vector<std::string> & params)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> operator ()(Func f)89 void operator()(Func f) 90 { 91 using boost::callable_traits::args_t; 92 erasedHandler = detail::Wrapped<Func, args_t<Func>>(std::move(f)); 93 } 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 103