TLA Line data Source code
1 : // evmone: Fast Ethereum Virtual Machine implementation
2 : // Copyright 2021 The evmone Authors.
3 : // SPDX-License-Identifier: Apache-2.0
4 :
5 : #pragma once
6 :
7 : #include <intx/intx.hpp>
8 : #include <cassert>
9 : #include <string>
10 : #include <string_view>
11 : #include <utility>
12 : #include <vector>
13 :
14 : namespace evmone::rlp
15 : {
16 : using bytes = std::basic_string<uint8_t>;
17 : using bytes_view = std::basic_string_view<uint8_t>;
18 :
19 : namespace internal
20 : {
21 : template <uint8_t ShortBase, uint8_t LongBase>
22 CBC 4232 : inline bytes encode_length(size_t l)
23 : {
24 : static constexpr uint8_t short_cutoff = 55;
25 : static_assert(ShortBase + short_cutoff <= 0xff);
26 4232 : assert(l <= 0xffffff);
27 :
28 4232 : if (l <= short_cutoff)
29 3063 : return {static_cast<uint8_t>(ShortBase + l)};
30 1169 : else if (const auto l0 = static_cast<uint8_t>(l); l <= 0xff)
31 957 : return {LongBase + 1, l0};
32 212 : else if (const auto l1 = static_cast<uint8_t>(l >> 8); l <= 0xffff)
33 212 : return {LongBase + 2, l1, l0};
34 : else
35 UBC 0 : return {LongBase + 3, static_cast<uint8_t>(l >> 16), l1, l0};
36 : }
37 :
38 CBC 1132 : inline bytes wrap_list(const bytes& content)
39 : {
40 2264 : return internal::encode_length<192, 247>(content.size()) + content;
41 : }
42 :
43 : template <typename InputIterator>
44 : inline bytes encode_container(InputIterator begin, InputIterator end);
45 : } // namespace internal
46 :
47 1608 : inline bytes_view trim(bytes_view b) noexcept
48 : {
49 1608 : b.remove_prefix(std::min(b.find_first_not_of(uint8_t{0x00}), b.size()));
50 1608 : return b;
51 : }
52 :
53 : template <typename T>
54 159 : inline decltype(rlp_encode(std::declval<T>())) encode(const T& v)
55 : {
56 159 : return rlp_encode(v);
57 : }
58 :
59 3824 : inline bytes encode(bytes_view data)
60 : {
61 : static constexpr uint8_t short_base = 128;
62 3824 : if (data.size() == 1 && data[0] < short_base)
63 724 : return {data[0]};
64 :
65 6200 : return internal::encode_length<short_base, 183>(data.size()) += data; // Op + not available.
66 : }
67 :
68 744 : inline bytes encode(uint64_t x)
69 : {
70 : uint8_t b[sizeof(x)];
71 744 : intx::be::store(b, x);
72 744 : return encode(trim({b, sizeof(b)}));
73 : }
74 :
75 638 : inline bytes encode(const intx::uint256& x)
76 : {
77 : uint8_t b[sizeof(x)];
78 638 : intx::be::store(b, x);
79 638 : return encode(trim({b, sizeof(b)}));
80 : }
81 :
82 : template <typename T>
83 108 : inline bytes encode(const std::vector<T>& v)
84 : {
85 108 : return internal::encode_container(v.begin(), v.end());
86 : }
87 :
88 : template <typename T, size_t N>
89 UBC 0 : inline bytes encode(const T (&v)[N])
90 : {
91 0 : return internal::encode_container(std::begin(v), std::end(v));
92 : }
93 :
94 : /// Encodes the fixed-size collection of heterogeneous values as RLP list.
95 : template <typename... Types>
96 CBC 371 : inline bytes encode_tuple(const Types&... elements)
97 : {
98 371 : return internal::wrap_list((encode(elements) + ...));
99 : }
100 :
101 : /// Encodes a pair of values as RPL list.
102 : template <typename T1, typename T2>
103 UBC 0 : inline bytes encode(const std::pair<T1, T2>& p)
104 : {
105 0 : return encode_tuple(p.first, p.second);
106 : }
107 :
108 : /// Encodes the container as RLP list.
109 : ///
110 : /// @tparam InputIterator Type of the input iterator.
111 : /// @param begin Begin iterator.
112 : /// @param end End iterator.
113 : /// @return Bytes of the RLP list.
114 : template <typename InputIterator>
115 CBC 108 : inline bytes internal::encode_container(InputIterator begin, InputIterator end)
116 : {
117 108 : bytes content;
118 108 : for (auto it = begin; it != end; ++it)
119 UBC 0 : content += encode(*it);
120 CBC 216 : return wrap_list(content);
121 108 : }
122 : } // namespace evmone::rlp
|