TARAXA
encoding_rlp.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <libdevcore/RLP.h>
4 
5 #include <optional>
6 
7 namespace taraxa::util {
8 using dev::RLP;
9 
11 struct RLPDecoderRef {
12  RLP const& value;
14 
16  RLPDecoderRef(RLP const& value, bool strict = false)
17  : RLPDecoderRef(value, strict ? RLP::VeryStrict : RLP::LaissezFaire) {}
18 };
19 
20 template <typename... Params>
21 void rlp_tuple(RLPEncoderRef encoding, Params const&... args);
22 
23 template <typename T>
24 auto rlp(RLPEncoderRef encoding, T const& target) -> decltype(RLP().toInt<T>(), void()) {
25  encoding.append(target);
26 }
27 
28 template <unsigned N>
29 void rlp(RLPEncoderRef encoding, dev::FixedHash<N> const& target) {
30  encoding.append(target);
31 }
32 
33 template <typename T>
34 inline auto rlp(RLPEncoderRef encoding, T const& target) -> decltype(target.rlp(encoding), void()) {
35  target.rlp(encoding);
36 }
37 
38 inline auto rlp(RLPEncoderRef encoding, std::string const& target) { encoding.append(target); }
39 
40 inline auto rlp(RLPEncoderRef encoding, dev::bytes const& target) { encoding.append(target); }
41 
42 template <typename Param>
43 void rlp(RLPEncoderRef encoding, std::optional<Param> const& target) {
44  if (target) {
45  rlp(encoding, *target);
46  } else {
47  encoding.append(unsigned(0));
48  }
49 }
50 
51 template <typename Param>
52 void rlp(RLPEncoderRef encoding, std::shared_ptr<Param> const& target) {
53  if (target) {
54  rlp(encoding, *target);
55  } else {
56  encoding.append(unsigned(0));
57  }
58 }
59 
60 template <typename T1, typename T2>
61 void rlp(RLPEncoderRef encoding, std::pair<T1, T2> const& target) {
62  rlp_tuple(encoding, target.first, target.second);
63 }
64 
65 template <typename Sequence>
66 auto rlp(RLPEncoderRef encoding, Sequence const& target)
67  -> decltype(target.size(), target.begin(), target.end(), void()) {
68  encoding.appendList(target.size());
69  for (auto const& v : target) {
70  rlp(encoding, v);
71  }
72 }
73 
74 template <typename Param, typename... Params>
75 void __enc_rlp_tuple_body__(RLPEncoderRef encoding, Param const& target, Params const&... rest) {
76  rlp(encoding, target);
77  if constexpr (sizeof...(rest) != 0) {
78  __enc_rlp_tuple_body__(encoding, rest...);
79  }
80 }
81 
82 template <typename... Params>
83 void rlp_tuple(RLPEncoderRef encoding, Params const&... args) {
84  constexpr auto num_elements = sizeof...(args);
85  static_assert(0 < num_elements);
86  encoding.appendList(num_elements);
87  __enc_rlp_tuple_body__(encoding, args...);
88 }
89 
90 template <typename... Params>
91 void rlp_tuple(RLPDecoderRef encoding, Params&... args);
92 
93 template <typename T>
94 auto rlp(RLPDecoderRef encoding, T& target) -> decltype(encoding.value.toInt<T>(), void()) {
95  target = encoding.value.toInt<T>(encoding.strictness);
96 }
97 
98 template <unsigned N>
99 void rlp(RLPDecoderRef encoding, dev::FixedHash<N>& target) {
100  target = encoding.value.toHash<dev::FixedHash<N>>(encoding.strictness);
101 }
102 
103 inline auto rlp(RLPDecoderRef encoding, std::string& target) { target = encoding.value.toString(encoding.strictness); }
104 
105 inline auto rlp(RLPDecoderRef encoding, dev::bytes& target) { target = encoding.value.toBytes(encoding.strictness); }
106 
107 template <typename Param>
108 void rlp(RLPDecoderRef encoding, std::optional<Param>& target) {
109  if (encoding.value.isNull() || encoding.value.isEmpty()) {
110  target = std::nullopt;
111  } else {
112  rlp(encoding, target.emplace());
113  }
114 }
115 
116 template <typename Param>
117 void rlp(RLPDecoderRef encoding, std::shared_ptr<Param>& target) {
118  if (encoding.value.isNull() || encoding.value.isEmpty()) {
119  target = nullptr;
120  } else {
121  target = std::make_shared<Param>();
122  rlp(encoding, *target);
123  }
124 }
125 
126 template <typename Sequence>
127 auto rlp(RLPDecoderRef encoding, Sequence& target) -> decltype(target.emplace_back(), void()) {
128  for (auto i : encoding.value) {
129  rlp(RLPDecoderRef(i, encoding.strictness), target.emplace_back());
130  }
131 }
132 inline void rlp(RLPDecoderRef encoding, bool& target) { target = encoding.value.toInt<uint8_t>(encoding.strictness); }
133 
134 template <typename T>
135 inline auto rlp(RLPDecoderRef encoding, T& target) -> decltype(target.rlp(encoding), void()) {
136  target.rlp(encoding);
137 }
138 
139 template <typename Map>
140 auto rlp(RLPDecoderRef encoding, Map& target) -> decltype(target[target.begin()->first], void()) {
141  using key_type = std::remove_cv_t<decltype(target.begin()->first)>;
142  for (auto i : encoding.value) {
143  auto entry_i = i.begin();
144  key_type key;
145  rlp(RLPDecoderRef(*entry_i, encoding.strictness), key);
146  rlp(RLPDecoderRef(*(++entry_i), encoding.strictness), target[key]);
147  }
148 }
149 
150 template <typename Param, typename... Params>
151 void __dec_rlp_tuple_body__(RLP::iterator& i, RLP::iterator const& end, RLP::Strictness strictness, Param& target,
152  Params&... rest) {
153  if (i == end) {
154  return;
155  }
156 
157  rlp(RLPDecoderRef(*i, strictness), target);
158 
159  if constexpr (sizeof...(rest) > 0) {
160  __dec_rlp_tuple_body__(++i, end, strictness, rest...);
161  }
162 }
163 
166 
167  InvalidEncodingSize(uint e, uint a) : expected(e), actual(a) {
168  RLPException() << dev::errinfo_comment("Invalid rlp list size") << dev::RequirementError(expected, actual);
169  }
170 };
171 
172 template <typename... Params>
173 void rlp_tuple(RLPDecoderRef encoding, Params&... args) {
174  constexpr auto num_elements = sizeof...(args);
175  static_assert(0 < num_elements);
176 
177  if (encoding.value.itemCount() != num_elements) {
178  throw InvalidEncodingSize(num_elements, encoding.value.itemCount());
179  }
180 
181  auto it_begin = encoding.value.begin();
182  __dec_rlp_tuple_body__(it_begin, encoding.value.end(), encoding.strictness, args...);
183 }
184 
185 template <typename T>
186 T rlp_dec(RLPDecoderRef encoding) {
187  T ret;
188  rlp(encoding, ret);
189  return ret;
190 }
191 
192 template <typename T>
193 dev::bytes const& rlp_enc(RLPEncoderRef encoder_to_reuse, T const& obj) {
194  encoder_to_reuse.clear();
195  rlp(encoder_to_reuse, obj);
196  return encoder_to_reuse.out();
197 }
198 
199 template <typename T>
200 dev::bytes rlp_enc(T const& obj) {
201  dev::RLPStream s;
202  rlp(s, obj);
203  return std::move(s.invalidate());
204 }
205 
206 } // namespace taraxa::util
207 
208 #define HAS_RLP_FIELDS \
209  void rlp(::taraxa::util::RLPDecoderRef encoding); \
210  void rlp(::taraxa::util::RLPEncoderRef encoding) const;
211 
212 #define RLP_FIELDS_DEFINE(_class_, ...) \
213  void _class_::rlp(::taraxa::util::RLPDecoderRef encoding) { ::taraxa::util::rlp_tuple(encoding, __VA_ARGS__); } \
214  void _class_::rlp(::taraxa::util::RLPEncoderRef encoding) const { ::taraxa::util::rlp_tuple(encoding, __VA_ARGS__); }
215 
216 #define RLP_FIELDS_DEFINE_INPLACE(...) \
217  void rlp(::taraxa::util::RLPDecoderRef encoding) { ::taraxa::util::rlp_tuple(encoding, __VA_ARGS__); } \
218  void rlp(::taraxa::util::RLPEncoderRef encoding) const { ::taraxa::util::rlp_tuple(encoding, __VA_ARGS__); }
Definition: FixedHash.h:35
Iterator class for iterating through items of RLP list.
Definition: RLP.h:148
Definition: RLP.h:56
_N toHash(int _flags=Strict) const
Definition: RLP.h:344
iterator begin() const
Iterator into beginning of sub-item list (valid only if we are a list).
Definition: RLP.h:175
size_t itemCount() const
Definition: RLP.h:106
iterator end() const
Iterator into end of sub-item list (valid only if we are a list).
Definition: RLP.h:178
bool isNull() const
No value.
Definition: RLP.h:91
int Strictness
Definition: RLP.h:69
bool isEmpty() const
Contains a zero-length string or zero-length list.
Definition: RLP.h:94
bytes toBytes(int _flags=LaissezFaire) const
Converts to bytearray.
Definition: RLP.h:215
std::string toString(int _flags=LaissezFaire) const
Converts to string.
Definition: RLP.h:235
std::enable_if_t< is_integer< _T >Signedness::any), _T > toInt(int _flags=Strict) const
Definition: RLP.h:309
Class for writing to an RLP bytestream.
Definition: RLP.h:484
void clear()
Clear the output stream so far.
Definition: RLP.h:608
std::enable_if_t< is_integer< N >Signedness::signed_only), RLPStream & > append(N const &_i)
Definition: RLP.h:498
RLPStream & appendList(size_t _items)
Appends a list.
Definition: RLP.cpp:207
bytes const & out() const
Read the byte stream.
Definition: RLP.h:614
bytes && invalidate()
Invalidate the object and steal the output byte stream.
Definition: RLP.h:620
boost::tuple< errinfo_required, errinfo_got > RequirementError
Definition: Exceptions.h:62
std::vector<::byte > bytes
Definition: Common.h:46
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:50
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
Definition: Common.h:92
Definition: default_construct_copyable_movable.hpp:10
void rlp_tuple(RLPEncoderRef encoding, Params const &... args)
Definition: encoding_rlp.hpp:83
T rlp_dec(RLPDecoderRef encoding)
Definition: encoding_rlp.hpp:186
auto rlp(RLPEncoderRef encoding, T const &target) -> decltype(RLP().toInt< T >(), void())
Definition: encoding_rlp.hpp:24
dev::RLPStream & RLPEncoderRef
Definition: encoding_rlp.hpp:10
dev::bytes const & rlp_enc(RLPEncoderRef encoder_to_reuse, T const &obj)
Definition: encoding_rlp.hpp:193
void __enc_rlp_tuple_body__(RLPEncoderRef encoding, Param const &target, Params const &... rest)
Definition: encoding_rlp.hpp:75
void __dec_rlp_tuple_body__(RLP::iterator &i, RLP::iterator const &end, RLP::Strictness strictness, Param &target, Params &... rest)
Definition: encoding_rlp.hpp:151
Base class for all RLP exceptions.
Definition: Exceptions.h:29
Definition: encoding_rlp.hpp:164
dev::bigint actual
Definition: encoding_rlp.hpp:165
dev::bigint expected
Definition: encoding_rlp.hpp:165
InvalidEncodingSize(uint e, uint a)
Definition: encoding_rlp.hpp:167
Definition: encoding_rlp.hpp:11
RLPDecoderRef(RLP const &value, bool strict=false)
Definition: encoding_rlp.hpp:16
RLPDecoderRef(RLP const &value, RLP::Strictness strictness)
Definition: encoding_rlp.hpp:15
RLP const & value
Definition: encoding_rlp.hpp:12
RLP::Strictness strictness
Definition: encoding_rlp.hpp:13