Skip to content

Commit 06882f8

Browse files
committed
multiprocess: Add serialization code for vector<char>
1 parent 095286f commit 06882f8

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

src/ipc/capnp/common-types.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,33 @@ decltype(auto) CustomReadField(TypeList<UniValue>, Priority<1>, InvokeContext& i
112112
value.read(std::string_view{data.begin(), data.size()});
113113
});
114114
}
115+
116+
//! Generic ::capnp::Data field builder for any C++ type that can be converted
117+
//! to a span of bytes, like std::vector<char> or std::array<uint8_t>, or custom
118+
//! blob types like uint256 or PKHash with data() and size() methods pointing to
119+
//! bytes.
120+
//!
121+
//! Note: it might make sense to move this function into libmultiprocess, since
122+
//! it is fairly generic. However this would require decreasing its priority so
123+
//! it can be overridden, which would require more changes inside
124+
//! libmultiprocess to avoid conflicting with the Priority<1> CustomBuildField
125+
//! function it already provides for std::vector. Also, it might make sense to
126+
//! provide a CustomReadField counterpart to this function, which could be
127+
//! called to read C++ types that can be constructed from spans of bytes from
128+
//! ::capnp::Data fields. But so far there hasn't been a need for this.
129+
template <typename LocalType, typename Value, typename Output>
130+
void CustomBuildField(TypeList<LocalType>, Priority<2>, InvokeContext& invoke_context, Value&& value, Output&& output)
131+
requires
132+
(std::is_same_v<decltype(output.get()), ::capnp::Data::Builder>) &&
133+
(std::convertible_to<Value, std::span<const std::byte>> ||
134+
std::convertible_to<Value, std::span<const char>> ||
135+
std::convertible_to<Value, std::span<const unsigned char>> ||
136+
std::convertible_to<Value, std::span<const signed char>>)
137+
{
138+
auto data = std::span{value};
139+
auto result = output.init(data.size());
140+
memcpy(result.begin(), data.data(), data.size());
141+
}
115142
} // namespace mp
116143

117144
#endif // BITCOIN_IPC_CAPNP_COMMON_TYPES_H

src/test/ipc_test.capnp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ interface FooInterface $Proxy.wrap("FooImplementation") {
1616
passOutPoint @1 (arg :Data) -> (result :Data);
1717
passUniValue @2 (arg :Text) -> (result :Text);
1818
passTransaction @3 (arg :Data) -> (result :Data);
19+
passVectorChar @4 (arg :Data) -> (result :Data);
1920
}

src/test/ipc_test.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ void IpcPipeTest()
9797
CTransactionRef tx2{foo->passTransaction(tx1)};
9898
BOOST_CHECK(*Assert(tx1) == *Assert(tx2));
9999

100+
std::vector<char> vec1{'H', 'e', 'l', 'l', 'o'};
101+
std::vector<char> vec2{foo->passVectorChar(vec1)};
102+
BOOST_CHECK_EQUAL(std::string_view(vec1.begin(), vec1.end()), std::string_view(vec2.begin(), vec2.end()));
103+
100104
// Test cleanup: disconnect pipe and join thread
101105
disconnect_client();
102106
thread.join();

src/test/ipc_test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class FooImplementation
1616
COutPoint passOutPoint(COutPoint o) { return o; }
1717
UniValue passUniValue(UniValue v) { return v; }
1818
CTransactionRef passTransaction(CTransactionRef t) { return t; }
19+
std::vector<char> passVectorChar(std::vector<char> v) { return v; }
1920
};
2021

2122
void IpcPipeTest();

0 commit comments

Comments
 (0)