@@ -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
0 commit comments