accumulators/codec.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2019 Aleksey Moskvin <zerg1996@yandex.ru>
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_ACCUMULATORS_CODEC_HPP
27 #define CRYPTO3_ACCUMULATORS_CODEC_HPP
28 
29 #include <boost/parameter/value_type.hpp>
30 
31 #include <boost/accumulators/framework/accumulator_base.hpp>
32 #include <boost/accumulators/framework/extractor.hpp>
33 #include <boost/accumulators/framework/depends_on.hpp>
34 #include <boost/accumulators/framework/parameters/sample.hpp>
35 
36 #include <boost/container/static_vector.hpp>
37 
38 #include <boost/range/algorithm.hpp>
39 
40 #include <nil/crypto3/detail/make_array.hpp>
41 #include <nil/crypto3/detail/digest.hpp>
42 
44 
45 namespace nil {
46  namespace crypto3 {
47  namespace accumulators {
48  template<typename CodecMode>
50  typedef CodecMode codec_mode_type;
51  };
52 
53  template<typename CodecMode>
54  struct preprocessing_accumulator_mode : public accumulator_mode<CodecMode> {
56  };
57 
58  template<typename CodecMode>
61  };
62 
63  namespace impl {
64  template<typename CodecMode, typename AccumulatorMode>
65  struct codec_impl : boost::accumulators::accumulator_base {
66  typedef CodecMode codec_mode_type;
67  typedef AccumulatorMode accumulator_mode_type;
68  };
69 
70  template<typename CodecMode>
71  struct codec_impl<CodecMode, preprocessing_accumulator_mode<CodecMode>>
72  : boost::accumulators::accumulator_base {
73  protected:
74  typedef CodecMode codec_mode_type;
76 
77  typedef typename codec_mode_type::finalizer_type finalizer_type;
78  typedef typename codec_mode_type::preprocessor_type preprocessor_type;
79 
80  constexpr static const std::size_t input_block_bits = codec_mode_type::input_block_bits;
81  constexpr static const std::size_t input_block_values = codec_mode_type::input_block_values;
82  typedef typename codec_mode_type::input_block_type input_block_type;
83 
84  constexpr static const std::size_t input_value_bits = codec_mode_type::input_value_bits;
85  typedef typename input_block_type::value_type input_value_type;
86 
87  constexpr static const std::size_t output_block_bits = codec_mode_type::output_block_bits;
88  constexpr static const std::size_t output_block_values = codec_mode_type::output_block_values;
89  typedef typename codec_mode_type::output_block_type output_block_type;
90 
91  constexpr static const std::size_t output_value_bits = codec_mode_type::output_value_bits;
92  typedef typename output_block_type::value_type output_value_type;
93 
94  typedef boost::container::static_vector<input_value_type, input_block_values> cache_type;
95 
96  public:
98 
99  codec_impl(boost::accumulators::dont_care) : seen(0) {
100  }
101 
102  template<typename ArgumentPack>
103  inline void operator()(const ArgumentPack &args) {
104  resolve_type(args[boost::accumulators::sample], args[bits | std::size_t()]);
105  }
106 
107  inline result_type result(boost::accumulators::dont_care) const {
108  result_type res = dgst;
109 
110  if (!cache.empty()) {
111  input_block_type ib = {0};
112  std::move(cache.begin(), cache.end(), ib.begin());
113  output_block_type ob = codec_mode_type::process_block(ib);
114  std::move(ob.begin(), ob.end(), std::inserter(res, res.end()));
115  }
116 
117  if (seen % input_block_bits) {
118  finalizer_type(input_block_bits - seen % input_block_bits)(res);
119  } else {
120  finalizer_type(0)(res);
121  }
122 
123  return res;
124  }
125 
126  protected:
127  inline void resolve_type(const input_value_type &value, std::size_t bits) {
128  if (bits == std::size_t()) {
129  process(value, input_value_bits);
130  } else {
131  process(value, bits);
132  }
133  }
134 
135  inline void resolve_type(const input_block_type &value, std::size_t bits) {
136  if (bits == std::size_t()) {
137  process(value, input_block_bits);
138  } else {
139  process(value, bits);
140  }
141  }
142 
143  inline void process(const input_value_type &value, std::size_t) {
144  if (cache.size() == cache.max_size()) {
145  input_block_type ib = {0};
146  std::move(cache.begin(), cache.end(), ib.begin());
147  output_block_type ob = codec_mode_type::process_block(ib);
148  std::move(ob.begin(), ob.end(), std::inserter(dgst, dgst.end()));
149 
150  cache.clear();
151  }
152 
153  cache.push_back(value);
154  seen += input_value_bits;
155  }
156 
157  inline void process(const input_block_type &block, std::size_t) {
159  if (cache.empty()) {
160  ob = codec_mode_type::process_block(block);
161  } else {
162  input_block_type b = make_array<input_block_values>(cache.begin(), cache.end());
163  typename input_block_type::const_iterator itr =
164  block.begin() + (cache.max_size() - cache.size());
165 
166  std::move(block.begin(), itr, b.end());
167 
168  ob = codec_mode_type::process_block(b);
169 
170  cache.clear();
171  cache.insert(cache.end(), itr, block.end());
172  }
173 
174  std::move(ob.begin(), ob.end(), std::inserter(dgst, dgst.end()));
175  seen += input_block_bits;
176  }
177 
178  std::size_t seen;
181  };
182 
183  template<typename CodecMode>
184  struct codec_impl<CodecMode, postprocessing_accumulator_mode<CodecMode>>
185  : boost::accumulators::accumulator_base {
186  protected:
187  typedef CodecMode codec_mode_type;
189 
190  typedef typename codec_mode_type::finalizer_type finalizer_type;
191  typedef typename codec_mode_type::preprocessor_type preprocessor_type;
192 
193  constexpr static const std::size_t input_block_bits = codec_mode_type::input_block_bits;
194  constexpr static const std::size_t input_block_values = codec_mode_type::input_block_values;
195  typedef typename codec_mode_type::input_block_type input_block_type;
196 
197  constexpr static const std::size_t input_value_bits = codec_mode_type::input_value_bits;
198  typedef typename input_block_type::value_type input_value_type;
199 
200  constexpr static const std::size_t output_block_bits = codec_mode_type::output_block_bits;
201  constexpr static const std::size_t output_block_values = codec_mode_type::output_block_values;
202  typedef typename codec_mode_type::output_block_type output_block_type;
203 
204  constexpr static const std::size_t output_value_bits = codec_mode_type::output_value_bits;
205  typedef typename output_block_type::value_type output_value_type;
206 
207  public:
209 
210  codec_impl(boost::accumulators::dont_care) : leading_zeros(0) {
211  }
212 
213  template<typename ArgumentPack>
214  inline void operator()(const ArgumentPack &args) {
215  preprocessor_type preprocessor;
216  const input_block_type block =
217  args[boost::accumulators::sample]; // TODO: I think it must be user type block like
218  // dgst
219  if (input.empty()) {
220  preprocessor(block);
221  leading_zeros = preprocessor.leading_zeros;
222  }
223  std::move(block.begin(), block.end(), std::back_inserter(input));
224  }
225 
226  inline result_type result(boost::accumulators::dont_care) const {
227  result_type res;
228  output_block_type ob = codec_mode_type::process_block(input);
229  std::move(ob.begin(), ob.end(), std::inserter(res, res.end()));
230  if (leading_zeros) {
231  finalizer_type fin(leading_zeros);
232  fin(res);
233  }
234  std::reverse(res.begin(), res.end());
235  return res;
236  }
237 
238  protected:
239  std::size_t leading_zeros;
241  }; // namespace impl
242  } // namespace impl
243 
244  namespace tag {
245  template<typename ProcessingMode>
246  struct codec : boost::accumulators::depends_on<> {
247  typedef ProcessingMode mode_type;
248 
251 
252  typedef boost::mpl::always<accumulators::impl::codec_impl<
253  mode_type, typename mode_type::codec_type::template accumulator_mode_type<ProcessingMode>>>
255  };
256  } // namespace tag
257 
258  namespace extract {
259  template<typename Mode, typename AccumulatorSet>
260  typename boost::mpl::apply<AccumulatorSet, tag::codec<Mode>>::type::result_type
261  codec(const AccumulatorSet &acc) {
262  return boost::accumulators::extract_result<tag::codec<Mode>>(acc);
263  }
264 
265  template<typename Codec, typename AccumulatorSet>
266  typename boost::mpl::apply<AccumulatorSet,
268  encode(const AccumulatorSet &acc) {
269  return boost::accumulators::extract_result<tag::codec<typename Codec::stream_encoder_type>>(acc);
270  }
271 
272  template<typename Codec, typename AccumulatorSet>
273  typename boost::mpl::apply<AccumulatorSet,
275  decode(const AccumulatorSet &acc) {
276  return boost::accumulators::extract_result<tag::codec<typename Codec::stream_decoder_type>>(acc);
277  }
278  } // namespace extract
279  } // namespace accumulators
280  } // namespace crypto3
281 } // namespace nil
282 
283 #endif // CRYPTO3_ACCUMULATORS_CODEC_HPP
boost::mpl::apply< AccumulatorSet, tag::codec< typename Codec::stream_decoder_type > >::type::result_type decode(const AccumulatorSet &acc)
Definition: accumulators/codec.hpp:275
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
boost::mpl::apply< AccumulatorSet, tag::codec< Mode > >::type::result_type codec(const AccumulatorSet &acc)
Definition: accumulators/codec.hpp:261
boost::mpl::apply< AccumulatorSet, tag::codec< typename Codec::stream_encoder_type > >::type::result_type encode(const AccumulatorSet &acc)
Definition: accumulators/codec.hpp:268
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
void reverse(Range &a, std::size_t n)
Definition: basic_operations.hpp:54
Definition: pair.hpp:31
Definition: accumulators/codec.hpp:49
CodecMode codec_mode_type
Definition: accumulators/codec.hpp:50
codec_mode_type::preprocessor_type preprocessor_type
Definition: accumulators/codec.hpp:191
codec_impl(boost::accumulators::dont_care)
Definition: accumulators/codec.hpp:210
void operator()(const ArgumentPack &args)
Definition: accumulators/codec.hpp:214
codec_mode_type::input_block_type input_block_type
Definition: accumulators/codec.hpp:195
output_block_type::value_type output_value_type
Definition: accumulators/codec.hpp:205
codec_mode_type::output_block_type output_block_type
Definition: accumulators/codec.hpp:202
postprocessing_accumulator_mode< CodecMode > accumulator_mode_type
Definition: accumulators/codec.hpp:188
codec_mode_type::finalizer_type finalizer_type
Definition: accumulators/codec.hpp:190
input_block_type::value_type input_value_type
Definition: accumulators/codec.hpp:198
result_type result(boost::accumulators::dont_care) const
Definition: accumulators/codec.hpp:226
void operator()(const ArgumentPack &args)
Definition: accumulators/codec.hpp:103
void process(const input_block_type &block, std::size_t)
Definition: accumulators/codec.hpp:157
codec_impl(boost::accumulators::dont_care)
Definition: accumulators/codec.hpp:99
input_block_type::value_type input_value_type
Definition: accumulators/codec.hpp:85
codec_mode_type::preprocessor_type preprocessor_type
Definition: accumulators/codec.hpp:78
codec_mode_type::output_block_type output_block_type
Definition: accumulators/codec.hpp:89
codec_mode_type::finalizer_type finalizer_type
Definition: accumulators/codec.hpp:77
void resolve_type(const input_value_type &value, std::size_t bits)
Definition: accumulators/codec.hpp:127
result_type result(boost::accumulators::dont_care) const
Definition: accumulators/codec.hpp:107
output_block_type::value_type output_value_type
Definition: accumulators/codec.hpp:92
preprocessing_accumulator_mode< CodecMode > accumulator_mode_type
Definition: accumulators/codec.hpp:75
codec_mode_type::input_block_type input_block_type
Definition: accumulators/codec.hpp:82
boost::container::static_vector< input_value_type, input_block_values > cache_type
Definition: accumulators/codec.hpp:94
void process(const input_value_type &value, std::size_t)
Definition: accumulators/codec.hpp:143
void resolve_type(const input_block_type &value, std::size_t bits)
Definition: accumulators/codec.hpp:135
Definition: accumulators/codec.hpp:65
CodecMode codec_mode_type
Definition: accumulators/codec.hpp:66
AccumulatorMode accumulator_mode_type
Definition: accumulators/codec.hpp:67
accumulator_mode< CodecMode >::codec_mode_type codec_mode_type
Definition: accumulators/codec.hpp:60
accumulator_mode< CodecMode >::codec_mode_type codec_mode_type
Definition: accumulators/codec.hpp:55
Definition: accumulators/codec.hpp:246
boost::mpl::always< accumulators::impl::codec_impl< mode_type, typename mode_type::codec_type::template accumulator_mode_type< ProcessingMode > > > impl
Definition: accumulators/codec.hpp:254
ProcessingMode mode_type
Definition: accumulators/codec.hpp:247