blob: d86035c61af19a7c0fb1a7128985fd14cb801774 [file] [log] [blame]
#ifndef BASYX_SHARED_OBJECT_OBJ_FUNCTION_H
#define BASYX_SHARED_OBJECT_OBJ_FUNCTION_H
#include <functional>
#include <BaSyx/shared/object/object_header.h>
#include <nlohmann/json.hpp>
namespace basyx {
namespace detail {
class functionWrapper
{
private:
std::function<basyx::object(basyx::object*)> func;
template <typename R, typename... Args, std::size_t... Is>
static R invoke_helper(std::function<R(Args...)> f, basyx::object::object_list_t & params, util::index_sequence<Is...>)
{
return f(params[Is].Get<Args&>()...);
};
public:
// Invoke wrapped function with no arguments
basyx::object invoke() const
{
return func(nullptr);
};
// Invoke wrapped function with argument
// Has to be primitive object or object list
basyx::object invoke(basyx::object & obj) const
{
return func(&obj);
};
// Wrap void function with no arguments
static functionWrapper wrap_func(std::function<void(void)> f)
{
functionWrapper fw;
fw.func = [f](basyx::object*)
{
f();
return basyx::object::make_null();
};
return fw;
};
// Wrap function with no arguments
template<typename RetType>
static functionWrapper wrap_func(std::function<RetType(void)> f)
{
functionWrapper fw;
fw.func = [f](basyx::object*)
{
return basyx::object{ f() };
};
return fw;
};
// Wrap function with single argument
template<typename RetType, typename Arg>
static functionWrapper wrap_func(std::function<RetType(Arg)> f)
{
functionWrapper fw;
fw.func = [f](basyx::object * obj)
{
// Only allow primitive object types
if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::Primitive && obj->GetValueType() == basyx::type::basyx_type<Arg>::value_type)
{
// Cast object to argument type and invoke
auto & i = obj->Get<Arg&>();
return basyx::object{ f(i) };
};
return basyx::object::make_null();
};
return fw;
};
// Wrap function with argument list
template<typename RetType, typename... Args>
static functionWrapper wrap_func(std::function<RetType(Args...)> f)
{
functionWrapper fw;
fw.func = [f](basyx::object * obj)
{
// Only allow object lists
if (obj != nullptr && obj->GetObjectType() == basyx::type::objectType::List && obj->GetValueType() == basyx::type::valueType::Object)
{
auto & list = obj->Get<basyx::object::object_list_t&>();
// if size of argument list differs from the functions parameter list, return null
if (list.size() != sizeof...(Args))
return basyx::object::make_null();
// TODO: type check arguments
// Invoke, using an integer sequence to pass the values from the list as single parameters to the function
return basyx::object{ invoke_helper<RetType, Args...>(f, list, util::make_index_sequence<sizeof...(Args)>{}) };
};
return basyx::object::make_null();
};
return fw;
};
template<typename T>
bool operator==(const T &) const
{
return false;
};
};
static void to_json(nlohmann::json & json, const functionWrapper &)
{
return;
};
}
}
#endif /* BASYX_SHARED_OBJECT_OBJ_FUNCTION_H */