6 #ifndef KAGOME_BLOB_HPP 7 #define KAGOME_BLOB_HPP 11 #include <fmt/format.h> 12 #include <boost/functional/hash.hpp> 13 #include <scale/scale.hpp> 19 #define KAGOME_BLOB_STRICT_TYPEDEF(space_name, class_name, blob_size) \ 20 namespace space_name { \ 21 struct class_name : public ::kagome::common::Blob<blob_size> { \ 22 using Base = ::kagome::common::Blob<blob_size>; \ 24 class_name() = default; \ 25 class_name(const class_name &) = default; \ 26 class_name(class_name &&) = default; \ 27 class_name &operator=(const class_name &) = default; \ 28 class_name &operator=(class_name &&) = default; \ 30 explicit class_name(const Base &blob) : Base{blob} {} \ 31 explicit class_name(Base &&blob) : Base{std::move(blob)} {} \ 33 ~class_name() = default; \ 35 class_name &operator=(const Base &blob) { \ 36 Blob::operator=(blob); \ 40 class_name &operator=(Base &&blob) { \ 41 Blob::operator=(std::move(blob)); \ 45 static ::outcome::result<class_name> fromString(std::string_view data) { \ 46 OUTCOME_TRY(blob, Base::fromString(data)); \ 47 return class_name{std::move(blob)}; \ 50 static ::outcome::result<class_name> fromHex(std::string_view hex) { \ 51 OUTCOME_TRY(blob, Base::fromHex(hex)); \ 52 return class_name{std::move(blob)}; \ 55 static ::outcome::result<class_name> fromHexWithPrefix( \ 56 std::string_view hex) { \ 57 OUTCOME_TRY(blob, Base::fromHexWithPrefix(hex)); \ 58 return class_name{std::move(blob)}; \ 61 static ::outcome::result<class_name> fromSpan( \ 62 const gsl::span<const uint8_t> &span) { \ 63 OUTCOME_TRY(blob, Base::fromSpan(span)); \ 64 return class_name{std::move(blob)}; \ 67 friend inline ::scale::ScaleEncoderStream &operator<<( \ 68 ::scale::ScaleEncoderStream &s, \ 69 const space_name::class_name &data) { \ 70 return s << static_cast<const Base &>(data); \ 73 friend inline ::scale::ScaleDecoderStream &operator>>( \ 74 ::scale::ScaleDecoderStream &s, space_name::class_name &data) { \ 75 return s >> static_cast<Base &>(data); \ 81 struct std::hash<space_name::class_name> { \ 82 auto operator()(const space_name::class_name &key) const { \ 84 return boost::hash_range(key.cbegin(), key.cend()); \ 89 struct fmt::formatter<space_name::class_name> \ 90 : fmt::formatter<space_name::class_name::Base> { \ 91 template <typename FormatCtx> \ 92 auto format(const space_name::class_name &blob, FormatCtx &ctx) { \ 93 return fmt::formatter<space_name::class_name::Base>::format(blob, ctx); \ 114 template <
size_t size_>
115 class Blob :
public std::array<byte_t, size_> {
118 static constexpr
bool is_static_collection =
true;
137 explicit Blob(
const std::array<byte_t, size_> &l) {
138 std::copy(l.begin(), l.end(), this->begin());
141 virtual ~
Blob() =
default;
146 constexpr
static size_t size() {
154 return std::string{this->begin(), this->end()};
160 std::string
toHex() const noexcept {
161 return hex_lower({this->begin(), this->end()});
169 static outcome::result<Blob<size_>>
fromString(std::string_view data) {
170 if (data.size() != size_) {
175 std::copy(data.begin(), data.end(), b.begin());
186 static outcome::result<Blob<size_>>
fromHex(std::string_view hex) {
187 OUTCOME_TRY(res,
unhex(hex));
188 return fromSpan(res);
198 std::string_view hex) {
200 return fromSpan(res);
209 const gsl::span<const uint8_t> &span) {
210 if (span.size() != size_) {
215 std::copy(span.begin(), span.end(), blob.begin());
234 inline std::ostream &operator<<(std::ostream &os, const Blob<N> &blob) {
235 return os << blob.
toHex();
241 struct std::hash<kagome::common::Blob<N>> {
243 return boost::hash_range(blob.data(), blob.data() + N);
248 struct fmt::formatter<
kagome::common::Blob<N>> {
250 char presentation = N > 4 ?
's' :
'l';
253 constexpr
auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) {
255 auto it = ctx.begin(), end = ctx.end();
256 if (it != end && (*it ==
's' || *it ==
'l')) {
257 presentation = *it++;
261 if (it != end && *it !=
'}') {
262 throw format_error(
"invalid format");
271 template <
typename FormatContext>
273 -> decltype(ctx.out()) {
276 if (presentation ==
's') {
281 htobe16(*reinterpret_cast<const uint16_t *>(blob.data())),
283 htobe16(*reinterpret_cast<const uint16_t *>(blob.data() + blob.size()
284 -
sizeof(uint16_t))));
287 return format_to(ctx.out(),
"0x{}", blob.toHex());
293 #endif // KAGOME_BLOB_HPP Blob(const std::array< byte_t, size_ > &l)
constructor enabling initializer list
std::string hex_lower(const gsl::span< const uint8_t > bytes) noexcept
Converts bytes to hex representation.
outcome::result< std::vector< uint8_t > > unhexWith0x(std::string_view hex_with_prefix)
Unhex hex-string with 0x in the begining.
const byte_t(&)[size_] const_narref
const_narref internal_array_reference() const
std::string toString() const noexcept
static outcome::result< Blob< size_ > > fromHexWithPrefix(std::string_view hex)
static outcome::result< Blob< size_ > > fromString(std::string_view data)
const byte_t(*)[size_] const_narptr
static outcome::result< Blob< size_ > > fromSpan(const gsl::span< const uint8_t > &span)
OUTCOME_HPP_DECLARE_ERROR(kagome::common, BlobError)
std::string toHex() const noexcept
auto operator()(const kagome::common::Blob< N > &blob) const
outcome::result< std::vector< uint8_t > > unhex(std::string_view hex)
Converts hex representation to bytes.
static constexpr size_t size()
static outcome::result< Blob< size_ > > fromHex(std::string_view hex)