Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit 549e668

Browse files
committed
Pack, unpack algorithms work for non-containerized integral type. #3
1 parent 2b68625 commit 549e668

File tree

5 files changed

+115
-80
lines changed

5 files changed

+115
-80
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2021 Mikhail Komarov <[email protected]>
3+
// Copyright (c) 2021 Nikita Kaskov <[email protected]>
4+
//
5+
// MIT License
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files (the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be included in all
15+
// copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
// SOFTWARE.
24+
//---------------------------------------------------------------------------//
25+
26+
#ifndef CRYPTO3_MARSHALLING_MULTIPRECISION_INFERENCE_TYPE_TRAITS_HPP
27+
#define CRYPTO3_MARSHALLING_MULTIPRECISION_INFERENCE_TYPE_TRAITS_HPP
28+
29+
// #include <nil/crypto3/marshalling/types/integral.hpp>
30+
31+
namespace nil {
32+
namespace crypto3 {
33+
namespace marshalling {
34+
namespace types {
35+
template<typename TTypeBase, typename IntegralContainer, typename... TOptions>
36+
class integral;
37+
} // namespace types
38+
} // namespace marshalling
39+
} // namespace crypto3
40+
namespace marshalling {
41+
42+
template<typename T, typename Enabled>
43+
class is_compatible;
44+
45+
template<typename Backend,
46+
nil::crypto3::multiprecision::expression_template_option ExpressionTemplates>
47+
class is_compatible <nil::crypto3::multiprecision::number<Backend, ExpressionTemplates>, void> {
48+
using default_endianness = option::big_endian;
49+
public:
50+
template <typename TEndian = default_endianness, typename... TOptions>
51+
using type = typename nil::crypto3::marshalling::types::integral<field_type<TEndian>,
52+
nil::crypto3::multiprecision::number<Backend, ExpressionTemplates>, TOptions...>;
53+
static const bool value = true;
54+
static const bool fixed_size = true;
55+
};
56+
57+
} // namespace marshalling
58+
} // namespace nil
59+
60+
#endif // CRYPTO3_MARSHALLING_MULTIPRECISION_INFERENCE_TYPE_TRAITS_HPP

include/nil/crypto3/marshalling/types/detail/integral/basic_fixed_precision_type.hpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ namespace nil {
121121

122122
template<typename TIter>
123123
nil::marshalling::status_type read(TIter &iter, std::size_t size) {
124-
// if (size < length()) {
125-
// return nil::marshalling::status_type::not_enough_data;
126-
// }
124+
if (size < length()) {
125+
return nil::marshalling::status_type::not_enough_data;
126+
}
127127

128128
read_no_status(iter);
129129
iter += max_length();
@@ -138,9 +138,9 @@ namespace nil {
138138

139139
template<typename TIter>
140140
nil::marshalling::status_type write(TIter &iter, std::size_t size) const {
141-
// if (size < length()) {
142-
// return nil::marshalling::status_type::buffer_overflow;
143-
// }
141+
if (size < length()) {
142+
return nil::marshalling::status_type::buffer_overflow;
143+
}
144144

145145
write_no_status(iter);
146146

include/nil/crypto3/marshalling/types/detail/integral/basic_non_fixed_precision_type.hpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,18 @@ namespace nil {
5151

5252
using base_impl_type = TTypeBase;
5353

54+
std::size_t cur_length = 0;
5455
public:
5556
using value_type = T;
5657
using serialized_type = value_type;
5758

5859
basic_integral() = default;
5960

6061
explicit basic_integral(value_type val) : value_(val) {
62+
63+
std::size_t bits_count = multiprecision::msb(val) + 1;
64+
65+
cur_length = bits_count / 8 + (bits_count%8?1:0);
6166
}
6267

6368
basic_integral(const basic_integral &) = default;
@@ -78,8 +83,8 @@ namespace nil {
7883
return value_;
7984
}
8085

81-
static constexpr std::size_t length() {
82-
return sizeof(serialized_type);
86+
std::size_t length() {
87+
return cur_length;
8388
}
8489

8590
static constexpr std::size_t min_length() {
@@ -105,20 +110,22 @@ namespace nil {
105110
// }
106111

107112
read_no_status(iter, size);
113+
iter += size;
114+
cur_length += size;
108115
return nil::marshalling::status_type::success;
109116
}
110117

111-
template<typename TIter>
112-
void read_no_status(TIter &iter) {
113-
read_no_status(length());
114-
}
118+
// template<typename TIter>
119+
// void read_no_status(TIter &iter) {
120+
// read_no_status(length());
121+
// }
115122

116123
private:
117124
template<typename TIter>
118125
void read_no_status(TIter &iter, std::size_t size) {
119126
value_ =
120127
crypto3::marshalling::processing::read_data<T, typename base_impl_type::endian_type>(
121-
iter, size);
128+
iter, size * 8);
122129
}
123130

124131
public:
@@ -129,6 +136,7 @@ namespace nil {
129136
// }
130137

131138
write_no_status(iter);
139+
iter += size;
132140
return nil::marshalling::status_type::success;
133141
}
134142

include/nil/crypto3/marshalling/types/integral.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
#include <nil/crypto3/marshalling/types/detail/integral/basic_fixed_precision_type.hpp>
4646
#include <nil/crypto3/marshalling/types/detail/integral/basic_non_fixed_precision_type.hpp>
47+
#include <nil/crypto3/marshalling/inference.hpp>
4748

4849
namespace nil {
4950
namespace crypto3 {
@@ -154,7 +155,7 @@ namespace nil {
154155

155156
/// @brief Get length required to serialise the current field value.
156157
/// @return Number of bytes it will take to serialise the field value.
157-
static constexpr std::size_t length() {
158+
std::size_t length() {
158159
return base_impl_type::length();
159160
}
160161

test/integral.cpp

+32-66
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#include <nil/crypto3/multiprecision/cpp_int.hpp>
4040
#include <nil/crypto3/multiprecision/number.hpp>
4141

42+
// #include <nil/crypto3/marshalling/algorithms/pack.hpp>
43+
#include <nil/marshalling/algorithms/pack.hpp>
44+
#include <nil/marshalling/algorithms/unpack.hpp>
4245
#include <nil/crypto3/marshalling/types/integral.hpp>
4346

4447
template<class T>
@@ -102,20 +105,16 @@ void test_round_trip_fixed_precision_big_endian(T val) {
102105

103106
export_bits(val, cv.begin() + begin_index, units_bits, true);
104107

105-
auto read_iter = cv.begin();
106-
nil::marshalling::status_type status = test_val.read(read_iter, cv.size() * units_bits);
107-
BOOST_CHECK(status == nil::marshalling::status_type::success);
108+
nil::marshalling::status_type status;
109+
T test_val1 = nil::marshalling::pack<nil::marshalling::option::big_endian, T>(cv, status);
108110

109-
BOOST_CHECK(val == test_val.value());
111+
BOOST_CHECK(val == test_val1);
112+
BOOST_CHECK(status == nil::marshalling::status_type::success);
110113

111-
std::vector<unit_type> test_val_byteblob;
112-
test_val_byteblob.resize(cv.size());
113-
auto write_iter = test_val_byteblob.begin();
114+
std::vector<unit_type> test_cv = nil::marshalling::unpack<nil::marshalling::option::big_endian, unit_type>(val, status);
114115

115-
status = test_val.write(write_iter, test_val_byteblob.size() * units_bits);
116+
BOOST_CHECK(std::equal(test_cv.begin(), test_cv.end(), cv.begin()));
116117
BOOST_CHECK(status == nil::marshalling::status_type::success);
117-
118-
BOOST_CHECK(cv == test_val_byteblob);
119118
}
120119

121120
template<class T>
@@ -133,24 +132,23 @@ void test_round_trip_fixed_precision_little_endian(T val) {
133132
export_bits(val, std::back_inserter(cv), units_bits, false);
134133
cv.resize(unitblob_size, 0x00);
135134

136-
auto read_iter = cv.begin();
137-
nil::marshalling::status_type status = test_val.read(read_iter, cv.size() * units_bits);
138-
BOOST_CHECK(status == nil::marshalling::status_type::success);
135+
nil::marshalling::status_type status;
136+
T test_val1 = nil::marshalling::pack<nil::marshalling::option::little_endian, T>(cv, status);
139137

140-
BOOST_CHECK(val == test_val.value());
138+
BOOST_CHECK(val == test_val1);
139+
BOOST_CHECK(status == nil::marshalling::status_type::success);
141140

142-
std::vector<unit_type> test_val_byteblob;
143-
test_val_byteblob.resize(cv.size());
144-
auto write_iter = test_val_byteblob.begin();
141+
std::vector<unit_type> test_cv = nil::marshalling::unpack<nil::marshalling::option::little_endian, unit_type>(val, status);
145142

146-
status = test_val.write(write_iter, test_val_byteblob.size() * units_bits);
143+
BOOST_CHECK(std::equal(test_cv.begin(), test_cv.end(), cv.begin()));
147144
BOOST_CHECK(status == nil::marshalling::status_type::success);
148-
149-
BOOST_CHECK(cv == test_val_byteblob);
150145
}
151146

152147
template<class T>
153148
void test_round_trip_fixed_precision() {
149+
150+
static_assert(nil::marshalling::is_compatible<T>::value);
151+
154152
std::cout << std::hex;
155153
std::cerr << std::hex;
156154
for (unsigned i = 0; i < 1000; ++i) {
@@ -160,72 +158,40 @@ void test_round_trip_fixed_precision() {
160158
}
161159
}
162160

163-
template<class T>
164-
void test_round_trip_non_fixed_precision_big_endian(T val) {
161+
template<typename TEndianness, class T>
162+
void test_round_trip_non_fixed_precision(T val) {
165163
using namespace nil::crypto3::marshalling;
166164

167165
std::size_t units_bits = 8;
168166
using unit_type = unsigned char;
169-
using integral_type = types::integral<nil::marshalling::field_type<nil::marshalling::option::big_endian>, T>;
170-
171-
integral_type test_val;
172167

173168
std::vector<unit_type> cv;
174-
export_bits(val, std::back_inserter(cv), units_bits, true);
175-
176-
auto read_iter = cv.begin();
177-
nil::marshalling::status_type status = test_val.read(read_iter, cv.size() * units_bits);
178-
BOOST_CHECK(status == nil::marshalling::status_type::success);
179-
180-
BOOST_CHECK(val == test_val.value());
181-
182-
std::vector<unit_type> test_val_byteblob;
183-
test_val_byteblob.resize(cv.size());
184-
auto write_iter = test_val_byteblob.begin();
185-
186-
status = test_val.write(write_iter, test_val_byteblob.size() * units_bits);
187-
BOOST_CHECK(status == nil::marshalling::status_type::success);
188-
189-
BOOST_CHECK(cv == test_val_byteblob);
190-
}
169+
export_bits(val, std::back_inserter(cv), units_bits,
170+
std::is_same<TEndianness, nil::marshalling::option::big_endian>::value?true:false);
191171

192-
template<class T>
193-
void test_round_trip_non_fixed_precision_little_endian(T val) {
194-
using namespace nil::crypto3::marshalling;
195-
196-
std::size_t units_bits = 8;
197-
using unit_type = unsigned char;
198-
using integral_type = types::integral<nil::marshalling::field_type<nil::marshalling::option::little_endian>, T>;
172+
nil::marshalling::status_type status;
173+
T test_val1 = nil::marshalling::pack<TEndianness, T>(cv, status);
199174

200-
integral_type test_val;
201-
202-
std::vector<unsigned char> cv;
203-
export_bits(val, std::back_inserter(cv), units_bits, false);
204-
205-
auto read_iter = cv.begin();
206-
nil::marshalling::status_type status = test_val.read(read_iter, cv.size() * units_bits);
175+
BOOST_CHECK(val == test_val1);
207176
BOOST_CHECK(status == nil::marshalling::status_type::success);
208177

209-
BOOST_CHECK(val == test_val.value());
178+
std::vector<unit_type> test_cv = nil::marshalling::unpack<TEndianness, unit_type>(val, status);
210179

211-
std::vector<unsigned char> test_val_byteblob;
212-
test_val_byteblob.resize(cv.size());
213-
auto write_iter = test_val_byteblob.begin();
214-
215-
status = test_val.write(write_iter, test_val_byteblob.size() * units_bits);
180+
BOOST_CHECK(std::equal(test_cv.begin(), test_cv.end(), cv.begin()));
216181
BOOST_CHECK(status == nil::marshalling::status_type::success);
217-
218-
BOOST_CHECK(cv == test_val_byteblob);
219182
}
220183

221184
template<class T>
222185
void test_round_trip_non_fixed_precision() {
186+
187+
static_assert(nil::marshalling::is_compatible<T>::value);
188+
223189
std::cout << std::hex;
224190
std::cerr << std::hex;
225191
for (unsigned i = 0; i < 1000; ++i) {
226192
T val = generate_random<T>();
227-
test_round_trip_non_fixed_precision_big_endian(val);
228-
test_round_trip_non_fixed_precision_little_endian(val);
193+
test_round_trip_non_fixed_precision<nil::marshalling::option::big_endian>(val);
194+
test_round_trip_non_fixed_precision<nil::marshalling::option::little_endian>(val);
229195
}
230196
}
231197

0 commit comments

Comments
 (0)