|
14 | 14 | #include <boost/multiprecision/cpp_int.hpp> |
15 | 15 | #include <qtils/tagged.hpp> |
16 | 16 |
|
| 17 | +#include <scale/definitions.hpp> |
| 18 | + |
17 | 19 | namespace scale { |
18 | 20 |
|
| 21 | + class ScaleEncoderStream; |
| 22 | + class ScaleDecoderStream; |
| 23 | + |
19 | 24 | using uint128_t = boost::multiprecision::uint128_t; |
20 | 25 | using uint256_t = boost::multiprecision::uint256_t; |
21 | 26 | using uint512_t = boost::multiprecision::uint512_t; |
@@ -65,6 +70,63 @@ namespace scale { |
65 | 70 |
|
66 | 71 | using Length = Compact<size_t>; |
67 | 72 |
|
| 73 | + template <typename T> |
| 74 | + inline T convert_to(const CompactCompatible auto &&value) { |
| 75 | + constexpr auto is_integral = |
| 76 | + std::unsigned_integral<std::remove_cvref_t<decltype(value)>>; |
| 77 | + if constexpr (is_integral) { |
| 78 | + return static_cast<T>(value); |
| 79 | + } else { |
| 80 | + return value.template convert_to<T>(); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + template <typename T> |
| 85 | + requires CompactCompatible<std::remove_cvref_t<T>> |
| 86 | + struct CompactReflection { |
| 87 | + private: |
| 88 | + template <typename U> |
| 89 | + explicit CompactReflection(U &&value) |
| 90 | + : temp_storage( |
| 91 | + std::is_lvalue_reference_v<U> |
| 92 | + ? std::nullopt |
| 93 | + : std::optional<std::decay_t<U>>(std::forward<U>(value))), |
| 94 | + ref(temp_storage ? *temp_storage : value) {} |
| 95 | + |
| 96 | + template <typename U> |
| 97 | + requires CompactCompatible<std::remove_cvref_t<U>> |
| 98 | + friend decltype(auto) as_compact(U &&value); |
| 99 | + |
| 100 | + public: |
| 101 | + CompactReflection(const CompactReflection &) = delete; |
| 102 | + CompactReflection &operator=(const CompactReflection &) = delete; |
| 103 | + CompactReflection(CompactReflection &&) = delete; |
| 104 | + CompactReflection &operator=(CompactReflection &&) = delete; |
| 105 | + |
| 106 | + friend ScaleEncoderStream &operator<<(ScaleEncoderStream &stream, |
| 107 | + const CompactReflection &value) { |
| 108 | + return stream << Compact<std::remove_cvref_t<T>>(value.ref); |
| 109 | + } |
| 110 | + friend ScaleDecoderStream &operator>>(ScaleDecoderStream &stream, |
| 111 | + const CompactReflection &value) { |
| 112 | + Compact<std::remove_cvref_t<T>> tmp; |
| 113 | + stream >> tmp; |
| 114 | + value.ref = untagged(tmp); |
| 115 | + return stream; |
| 116 | + } |
| 117 | + |
| 118 | + private: |
| 119 | + std::optional<std::decay_t<T>> temp_storage; |
| 120 | + T &ref; |
| 121 | + }; |
| 122 | + |
| 123 | + template <typename T> |
| 124 | + requires CompactCompatible<std::remove_cvref_t<T>> |
| 125 | + decltype(auto) as_compact(T &&value) { |
| 126 | + return CompactReflection<decltype(value)>( |
| 127 | + std::forward<decltype(value)>(value)); |
| 128 | + } |
| 129 | + |
68 | 130 | /// @brief OptionalBool is internal extended bool type |
69 | 131 | enum class OptionalBool : uint8_t { |
70 | 132 | NONE = 0u, |
|
0 commit comments