diff --git a/include/mp/proxy-types.h b/include/mp/proxy-types.h index 70b05381..5adab96f 100644 --- a/include/mp/proxy-types.h +++ b/include/mp/proxy-types.h @@ -280,6 +280,17 @@ struct ListOutput<::capnp::List> // clang-format on }; +template +void BuildList(TypeList, InvokeContext& invoke_context, Output&& output, Value&& value) +{ + auto list = output.init(value.size()); + size_t i = 0; + for (const auto& elem : value) { + BuildField(TypeList(), invoke_context, ListOutput(list, i), elem); + ++i; + } +} + template void CustomBuildField(TypeList, Priority<0>, InvokeContext& invoke_context, Value&& value, Output&& output) { diff --git a/include/mp/type-map.h b/include/mp/type-map.h index 50a590cb..213ed811 100644 --- a/include/mp/type-map.h +++ b/include/mp/type-map.h @@ -17,14 +17,7 @@ void CustomBuildField(TypeList>, 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>(), invoke_context, - ListOutput(list, i), elem); - ++i; - } + BuildList(TypeList>(), invoke_context, output, value); } // Replacement for `m.emplace(piecewise_construct, t1, t2)` to work around a diff --git a/include/mp/type-set.h b/include/mp/type-set.h index 699c6e9e..f051f738 100644 --- a/include/mp/type-set.h +++ b/include/mp/type-set.h @@ -16,13 +16,7 @@ void CustomBuildField(TypeList>, 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(), invoke_context, ListOutput(list, i), elem); - ++i; - } + BuildList(TypeList(), invoke_context, output, value); } template diff --git a/include/mp/type-unordered-set.h b/include/mp/type-unordered-set.h new file mode 100644 index 00000000..ad4c0ab8 --- /dev/null +++ b/include/mp/type-unordered-set.h @@ -0,0 +1,43 @@ +// 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 +#include +#include + +namespace mp { +template +void CustomBuildField(TypeList>, + Priority<1>, + InvokeContext& invoke_context, + Value&& value, + Output&& output) +{ + BuildList(TypeList(), invoke_context, output, value); +} + +template +decltype(auto) CustomReadField(TypeList>, + Priority<1>, + InvokeContext& invoke_context, + Input&& input, + ReadDest&& read_dest) +{ + return read_dest.update([&](auto& value) { + auto data = input.get(); + value.clear(); + for (auto item : data) { + ReadField(TypeList(), invoke_context, Make(item), + ReadDestEmplace(TypeList(), [&](auto&&... args) -> auto& { + return *value.emplace(std::forward(args)...).first; + })); + } + }); +} +} // namespace mp + +#endif // MP_PROXY_TYPE_UNORDERED_SET_H \ No newline at end of file diff --git a/include/mp/type-vector.h b/include/mp/type-vector.h index 90605ddf..648fda5d 100644 --- a/include/mp/type-vector.h +++ b/include/mp/type-vector.h @@ -16,12 +16,7 @@ void CustomBuildField(TypeList>, 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(), invoke_context, ListOutput(list, i), *it); - } + BuildList(TypeList(), invoke_context, output, value); } inline static bool BuildPrimitive(InvokeContext& invoke_context, std::vector::const_reference value, TypeList) diff --git a/test/mp/test/foo-types.h b/test/mp/test/foo-types.h index bd5565aa..b96eabfc 100644 --- a/test/mp/test/foo-types.h +++ b/test/mp/test/foo-types.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/test/mp/test/foo.capnp b/test/mp/test/foo.capnp index 99e918a3..562f249f 100644 --- a/test/mp/test/foo.capnp +++ b/test/mp/test/foo.capnp @@ -53,10 +53,11 @@ interface FooFn $Proxy.wrap("ProxyCallback>") { 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") { diff --git a/test/mp/test/foo.h b/test/mp/test/foo.h index 4d52fd0d..7ec59fcc 100644 --- a/test/mp/test/foo.h +++ b/test/mp/test/foo.h @@ -12,6 +12,7 @@ #include #include #include +#include #include namespace mp { @@ -20,9 +21,10 @@ namespace test { struct FooStruct { std::string name; - std::set setint; - std::vector vbool; + std::set set_int; + std::vector v_bool; std::optional optional_int; + std::unordered_set unordered_set_int; }; enum class FooEnum : uint8_t { ONE = 1, TWO = 2, }; diff --git a/test/mp/test/test.cpp b/test/mp/test/test.cpp index 1d3b19bf..13fc8e30 100644 --- a/test/mp/test/test.cpp +++ b/test/mp/test/test.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -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);