multiprocess: update common-types.h to use C++20 concepts

Idea came from review comment by ion-
https://github.com/bitcoin/bitcoin/pull/30510#discussion_r1757372497
pull/30510/head
Ryan Ofsky 2 months ago
parent 206c6e78ee
commit 69dfeb1876

@ -6,6 +6,7 @@
#define BITCOIN_IPC_CAPNP_COMMON_TYPES_H
#include <clientversion.h>
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
@ -16,33 +17,6 @@
namespace ipc {
namespace capnp {
//! Use SFINAE to define Serializeable<T> trait which is true if type T has a
//! Serialize(stream) method, false otherwise.
template <typename T>
struct Serializable {
private:
template <typename C>
static std::true_type test(decltype(std::declval<C>().Serialize(std::declval<std::nullptr_t&>()))*);
template <typename>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr))::value;
};
//! Use SFINAE to define Unserializeable<T> trait which is true if type T has
//! an Unserialize(stream) method, false otherwise.
template <typename T>
struct Unserializable {
private:
template <typename C>
static std::true_type test(decltype(std::declval<C>().Unserialize(std::declval<std::nullptr_t&>()))*);
template <typename>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr))::value;
};
} // namespace capnp
} // namespace ipc
@ -50,18 +24,16 @@ public:
namespace mp {
//! Overload multiprocess library's CustomBuildField hook to allow any
//! serializable object to be stored in a capnproto Data field or passed to a
//! canproto interface. Use Priority<1> so this hook has medium priority, and
//! capnproto interface. Use Priority<1> so this hook has medium priority, and
//! higher priority hooks could take precedence over this one.
template <typename LocalType, typename Value, typename Output>
void CustomBuildField(
TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output,
// Enable if serializeable and if LocalType is not cv or reference
// qualified. If LocalType is cv or reference qualified, it is important to
// fall back to lower-priority Priority<0> implementation of this function
// that strips cv references, to prevent this CustomBuildField overload from
// taking precedence over more narrow overloads for specific LocalTypes.
std::enable_if_t<ipc::capnp::Serializable<LocalType>::value &&
std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>>* enable = nullptr)
void CustomBuildField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)
// Enable if serializeable and if LocalType is not cv or reference qualified. If
// LocalType is cv or reference qualified, it is important to fall back to
// lower-priority Priority<0> implementation of this function that strips cv
// references, to prevent this CustomBuildField overload from taking precedence
// over more narrow overloads for specific LocalTypes.
requires Serializable<LocalType, DataStream> && std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>
{
DataStream stream;
value.Serialize(stream);
@ -71,12 +43,11 @@ void CustomBuildField(
//! Overload multiprocess library's CustomReadField hook to allow any object
//! with an Unserialize method to be read from a capnproto Data field or
//! returned from canproto interface. Use Priority<1> so this hook has medium
//! returned from capnproto interface. Use Priority<1> so this hook has medium
//! priority, and higher priority hooks could take precedence over this one.
template <typename LocalType, typename Input, typename ReadDest>
decltype(auto)
CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest,
std::enable_if_t<ipc::capnp::Unserializable<LocalType>::value>* enable = nullptr)
decltype(auto) CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest)
requires Unserializable<LocalType, DataStream>
{
return read_dest.update([&](auto& value) {
if (!input.has()) return;
@ -86,6 +57,8 @@ CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context,
});
}
//! Overload CustomBuildField and CustomReadField to serialize UniValue
//! parameters and return values as JSON strings.
template <typename Value, typename Output>
void CustomBuildField(TypeList<UniValue>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)
{

Loading…
Cancel
Save