Skip to content

Commit ccef888

Browse files
committed
Start working on the Bridge class
1 parent 0629430 commit ccef888

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/cpp/lib/testml/bridge.hpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#include <tuple>
4+
#include <utility>
5+
#include <unordered_map>
6+
#include <memory>
7+
#include <stdexcept>
8+
#include "../../ext/nlohmann/json.hpp"
9+
10+
namespace testml {
11+
12+
namespace details {
13+
14+
using json = nlohmann::json;
15+
16+
// we need this details class so that we can have a non-templated value
17+
struct FnHolder {
18+
virtual json call(std::vector<json> const&) = 0;
19+
};
20+
21+
template<typename Ret, typename... Arg>
22+
class FnHolderImpl : public FnHolder {
23+
using Fn = Ret(*)(Arg...);
24+
Fn _fn;
25+
26+
// type of the N-th argument that the stored function takes
27+
template<std::size_t>
28+
using ArgType = std::tuple_element<I, std::tuple<Arg...>>;
29+
30+
// uncook each argument to its expected type, and call the function
31+
template<std::size_t... I>
32+
Ret call_impl(std::vector<json> const& args, std::index_sequence<I...>) {
33+
return _fn(uncook<ArgType<I>>(args[I]), ...);
34+
}
35+
36+
public:
37+
FnHolderImpl(Fn fn) : _fn{std::move(fn)} {
38+
}
39+
40+
// check arity and call the function using our little helper, before wrapping it back to json
41+
json call(std::vector<json> const& args) override {
42+
if (args.size() != sizeof...(Arg)) {
43+
throw new std::runtime_error("Bridge method call with wrong arity, expected " + sizeof...(Arg) + ", got " + args.size() + ".");
44+
}
45+
46+
return cook(_call(args, std::make_index_sequence<sizeof...(Arg)>{}));
47+
}
48+
49+
};
50+
51+
}
52+
53+
class Bridge {
54+
std::unordered_map<std::string, std::unique_ptr<details::FnHolder>> _fns;
55+
56+
public:
57+
template<typename Fn>
58+
void register(std::string const& name, Fn&& fn) {
59+
_fns[name] = std:make_unique<details::FnHolderImpl>(std::move(fn));
60+
}
61+
62+
json call(std::string const& name, std::vector<json> const& args) override {
63+
auto it = _fns.find(name);
64+
if (it == _fns.end()) {
65+
throw new std::runtime_error("Bridge method not found: " + name + ".");
66+
}
67+
return it->call(args);
68+
}
69+
};
70+
71+
}

0 commit comments

Comments
 (0)