Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/mp/proxy-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,30 @@ struct ListOutput<::capnp::List<T, kind>>
// clang-format on
};

template <typename LocalType, typename Value, typename Output>
void BuildList(TypeList<LocalType>, InvokeContext& invoke_context, Output&& output, Value&& value)
{
auto list = output.init(value.size());
size_t i = 0;
for (const auto& elem : value) {
BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), elem);
++i;
}
}

template <typename LocalType, typename Input, typename InitFn, typename EmplaceFn>
void ReadList(TypeList<LocalType>, InvokeContext& invoke_context, Input&& input, InitFn&& init, EmplaceFn&& emplace)
{
auto data = input.get();
init(data.size());
for (auto item : data) {
ReadField(TypeList<LocalType>(), invoke_context, Make<ValueField>(item),
ReadDestEmplace(TypeList<LocalType>(), [&emplace](auto&&... args) -> decltype(auto) {
return emplace(std::forward<decltype(args)>(args)...);
}));
}
}

template <typename LocalType, typename Value, typename Output>
void CustomBuildField(TypeList<LocalType>, Priority<0>, InvokeContext& invoke_context, Value&& value, Output&& output)
{
Expand Down
25 changes: 7 additions & 18 deletions include/mp/type-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@ void CustomBuildField(TypeList<std::map<KeyLocalType, ValueLocalType>>,
Value&& value,
Output&& output)
{
// FIXME dededup with vector handler above
auto list = output.init(value.size());
size_t i = 0;
for (const auto& elem : value) {
BuildField(TypeList<std::pair<KeyLocalType, ValueLocalType>>(), invoke_context,
ListOutput<typename decltype(list)::Builds>(list, i), elem);
++i;
}
BuildList(TypeList<std::pair<KeyLocalType, ValueLocalType>>(), invoke_context, output, value);
}

// Replacement for `m.emplace(piecewise_construct, t1, t2)` to work around a
Expand Down Expand Up @@ -64,16 +57,12 @@ decltype(auto) CustomReadField(TypeList<std::map<KeyLocalType, ValueLocalType>>,
ReadDest&& read_dest)
{
return read_dest.update([&](auto& value) {
auto data = input.get();
value.clear();
for (auto item : data) {
ReadField(TypeList<std::pair<const KeyLocalType, ValueLocalType>>(), invoke_context,
Make<ValueField>(item),
ReadDestEmplace(
TypeList<std::pair<const KeyLocalType, ValueLocalType>>(), [&](auto&&... args) -> auto& {
return *EmplacePiecewiseSafe(value, std::forward<decltype(args)>(args)...).first;
}));
}
ReadList(
TypeList<std::pair<const KeyLocalType, ValueLocalType>>(), invoke_context, input,
[&](size_t) { value.clear(); },
[&](auto&&... args) -> auto& {
return *EmplacePiecewiseSafe(value, std::forward<decltype(args)>(args)...).first;
});
});
}
} // namespace mp
Expand Down
22 changes: 7 additions & 15 deletions include/mp/type-set.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@ void CustomBuildField(TypeList<std::set<LocalType>>,
Value&& value,
Output&& output)
{
// FIXME dededup with vector handler above
auto list = output.init(value.size());
size_t i = 0;
for (const auto& elem : value) {
BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), elem);
++i;
}
BuildList(TypeList<LocalType>(), invoke_context, output, value);
}

template <typename LocalType, typename Input, typename ReadDest>
Expand All @@ -33,14 +27,12 @@ decltype(auto) CustomReadField(TypeList<std::set<LocalType>>,
ReadDest&& read_dest)
{
return read_dest.update([&](auto& value) {
auto data = input.get();
value.clear();
for (auto item : data) {
ReadField(TypeList<LocalType>(), invoke_context, Make<ValueField>(item),
ReadDestEmplace(TypeList<const LocalType>(), [&](auto&&... args) -> auto& {
return *value.emplace(std::forward<decltype(args)>(args)...).first;
}));
}
ReadList(
TypeList<LocalType>(), invoke_context, input,
[&](size_t) { value.clear(); },
[&](auto&&... args) -> auto& {
return *value.emplace(std::forward<decltype(args)>(args)...).first;
});
});
}
} // namespace mp
Expand Down
44 changes: 44 additions & 0 deletions include/mp/type-unordered-set.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef MP_PROXY_TYPE_UNORDERED_SET_H
#define MP_PROXY_TYPE_UNORDERED_SET_H

#include <mp/proxy-types.h>
#include <mp/util.h>
#include <unordered_set>

namespace mp {
template <typename LocalType, typename Value, typename Output>
void CustomBuildField(TypeList<std::unordered_set<LocalType>>,
Priority<1>,
InvokeContext& invoke_context,
Value&& value,
Output&& output)
{
BuildList(TypeList<LocalType>(), invoke_context, output, value);
}

template <typename LocalType, typename Input, typename ReadDest>
decltype(auto) CustomReadField(TypeList<std::unordered_set<LocalType>>,
Priority<1>,
InvokeContext& invoke_context,
Input&& input,
ReadDest&& read_dest)
{
return read_dest.update([&](auto& value) {
ReadList(
TypeList<LocalType>(), invoke_context, input,
[&](size_t size) {
value.clear();
value.reserve(size);
},
[&](auto&&... args) -> auto& {
return *value.emplace(std::forward<decltype(args)>(args)...).first;
});
});
}
} // namespace mp

#endif // MP_PROXY_TYPE_UNORDERED_SET_H
27 changes: 11 additions & 16 deletions include/mp/type-vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ void CustomBuildField(TypeList<std::vector<LocalType>>,
Value&& value,
Output&& output)
{
// FIXME dedup with set handler below
auto list = output.init(value.size());
size_t i = 0;
for (auto it = value.begin(); it != value.end(); ++it, ++i) {
BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), *it);
}
BuildList(TypeList<LocalType>(), invoke_context, output, value);
}

inline static bool BuildPrimitive(InvokeContext& invoke_context, std::vector<bool>::const_reference value, TypeList<bool>)
Expand All @@ -37,16 +32,16 @@ decltype(auto) CustomReadField(TypeList<std::vector<LocalType>>,
ReadDest&& read_dest)
{
return read_dest.update([&](auto& value) {
auto data = input.get();
value.clear();
value.reserve(data.size());
for (auto item : data) {
ReadField(TypeList<LocalType>(), invoke_context, Make<ValueField>(item),
ReadDestEmplace(TypeList<LocalType>(), [&](auto&&... args) -> auto& {
value.emplace_back(std::forward<decltype(args)>(args)...);
return value.back();
}));
}
ReadList(
TypeList<LocalType>(), invoke_context, input,
[&](size_t size) {
value.clear();
value.reserve(size);
},
[&](auto&&... args) -> auto& {
value.emplace_back(std::forward<decltype(args)>(args)...);
return value.back();
});
});
}

Expand Down
1 change: 1 addition & 0 deletions test/mp/test/foo-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <mp/type-string.h>
#include <mp/type-struct.h>
#include <mp/type-threadmap.h>
#include <mp/type-unordered-set.h>
#include <mp/type-vector.h>
#include <string>
#include <type_traits>
Expand Down
5 changes: 3 additions & 2 deletions test/mp/test/foo.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ interface FooFn $Proxy.wrap("ProxyCallback<std::function<int()>>") {

struct FooStruct $Proxy.wrap("mp::test::FooStruct") {
name @0 :Text;
setint @1 :List(Int32);
vbool @2 :List(Bool);
setInt @1 :List(Int32) $Proxy.name("set_int");
vBool @2 :List(Bool) $Proxy.name("v_bool");
optionalInt @3 :Int32 $Proxy.name("optional_int");
hasOptionalInt @4 :Bool;
unorderedSetInt @5 :List(Int32) $Proxy.name("unordered_set_int");
}

struct FooCustom $Proxy.wrap("mp::test::FooCustom") {
Expand Down
6 changes: 4 additions & 2 deletions test/mp/test/foo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <optional>
#include <string>
#include <set>
#include <unordered_set>
#include <vector>

namespace mp {
Expand All @@ -20,9 +21,10 @@ namespace test {
struct FooStruct
{
std::string name;
std::set<int> setint;
std::vector<bool> vbool;
std::set<int> set_int;
std::vector<bool> v_bool;
std::optional<int> optional_int;
std::unordered_set<int> unordered_set_int;
};

enum class FooEnum : uint8_t { ONE = 1, TWO = 2, };
Expand Down
27 changes: 17 additions & 10 deletions test/mp/test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <string_view>
#include <thread>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -141,21 +142,27 @@ KJ_TEST("Call FooInterface methods")

FooStruct in;
in.name = "name";
in.setint.insert(2);
in.setint.insert(1);
in.vbool.push_back(false);
in.vbool.push_back(true);
in.vbool.push_back(false);
in.set_int.insert(2);
in.set_int.insert(1);
in.unordered_set_int.insert(2);
in.unordered_set_int.insert(1);
in.v_bool.push_back(false);
in.v_bool.push_back(true);
in.v_bool.push_back(false);
in.optional_int = 3;
FooStruct out = foo->pass(in);
KJ_EXPECT(in.name == out.name);
KJ_EXPECT(in.setint.size() == out.setint.size());
for (auto init{in.setint.begin()}, outit{out.setint.begin()}; init != in.setint.end() && outit != out.setint.end(); ++init, ++outit) {
KJ_EXPECT(in.set_int.size() == out.set_int.size());
for (auto init{in.set_int.begin()}, outit{out.set_int.begin()}; init != in.set_int.end() && outit != out.set_int.end(); ++init, ++outit) {
KJ_EXPECT(*init == *outit);
}
KJ_EXPECT(in.vbool.size() == out.vbool.size());
for (size_t i = 0; i < in.vbool.size(); ++i) {
KJ_EXPECT(in.vbool[i] == out.vbool[i]);
KJ_EXPECT(in.unordered_set_int.size() == out.unordered_set_int.size());
for (const auto& elem : in.unordered_set_int) {
KJ_EXPECT(out.unordered_set_int.count(elem) == 1);
}
KJ_EXPECT(in.v_bool.size() == out.v_bool.size());
for (size_t i = 0; i < in.v_bool.size(); ++i) {
KJ_EXPECT(in.v_bool[i] == out.v_bool[i]);
}
KJ_EXPECT(in.optional_int == out.optional_int);

Expand Down
Loading