|
| 1 | +// Copyright (c) 2025 The Bitcoin Core developers |
| 2 | +// Distributed under the MIT software license, see the accompanying |
| 3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 4 | + |
| 5 | +#ifndef MP_PROXY_TYPE_DATA_H |
| 6 | +#define MP_PROXY_TYPE_DATA_H |
| 7 | + |
| 8 | +#include <mp/util.h> |
| 9 | + |
| 10 | +namespace mp { |
| 11 | +template <typename T, typename U> |
| 12 | +concept IsSpanOf = |
| 13 | + std::convertible_to<T, std::span<const U>> && |
| 14 | + std::constructible_from<T, const U*, const U*>; |
| 15 | + |
| 16 | +template <typename T> |
| 17 | +concept IsByteSpan = |
| 18 | + IsSpanOf<T, std::byte> || |
| 19 | + IsSpanOf<T, char> || |
| 20 | + IsSpanOf<T, unsigned char> || |
| 21 | + IsSpanOf<T, signed char>; |
| 22 | + |
| 23 | +//! Generic ::capnp::Data field builder for any C++ type that can be converted |
| 24 | +//! to a span of bytes, like std::vector<char> or std::array<uint8_t>, or custom |
| 25 | +//! blob types like uint256 or PKHash with data() and size() methods pointing to |
| 26 | +//! bytes. |
| 27 | +template <typename LocalType, typename Value, typename Output> |
| 28 | +void CustomBuildField(TypeList<LocalType>, Priority<2>, InvokeContext& invoke_context, Value&& value, Output&& output) |
| 29 | +requires (std::is_same_v<decltype(output.get()), ::capnp::Data::Builder> && IsByteSpan<LocalType>) |
| 30 | +{ |
| 31 | + auto data = std::span{value}; |
| 32 | + auto result = output.init(data.size()); |
| 33 | + memcpy(result.begin(), data.data(), data.size()); |
| 34 | +} |
| 35 | + |
| 36 | +template <typename LocalType, typename Input, typename ReadDest> |
| 37 | +decltype(auto) CustomReadField(TypeList<LocalType>, Priority<2>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest) |
| 38 | +requires (std::is_same_v<decltype(input.get()), ::capnp::Data::Reader> && IsByteSpan<LocalType>) |
| 39 | +{ |
| 40 | + using ByteType = decltype(std::span{std::declval<LocalType>().begin(), std::declval<LocalType>().end()})::element_type; |
| 41 | + const kj::byte *begin{input.get().begin()}, *end{input.get().end()}; |
| 42 | + return read_dest.construct(reinterpret_cast<const ByteType*>(begin), reinterpret_cast<const ByteType*>(end)); |
| 43 | +} |
| 44 | +} // namespace mp |
| 45 | + |
| 46 | +#endif // MP_PROXY_TYPE_DATA_H |
0 commit comments