passhash/include/nil/crypto3/detail/imploder.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 //
4 // MIT License
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //---------------------------------------------------------------------------//
24 
25 #ifndef CRYPTO3_DETAIL_IMPLODER_HPP
26 #define CRYPTO3_DETAIL_IMPLODER_HPP
27 
28 #include <nil/crypto3/detail/stream_endian.hpp>
29 #include <nil/crypto3/detail/unbounded_shift.hpp>
30 
31 #include <boost/static_assert.hpp>
32 
33 #include <climits>
34 #include <cstring>
35 
36 namespace nil {
37  namespace crypto3 {
38  namespace detail {
39 
40  // By definition, for all imploders, InputBits < OutputBits,
41  // so we're taking many smaller values and combining them into one value
42  // @formatter:off
43 
44  template<typename Endianness, int InputBits, int OutputBits, int k>
45  struct imploder_step;
46 
47  template<int UnitBits, int InputBits, int OutputBits, int k>
48  struct imploder_step<stream_endian::big_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
49  template<typename InputValue, typename OutputValue>
50  static void step(InputValue z, OutputValue &x) {
51  int const shift = OutputBits - (InputBits + k);
52  OutputValue y = low_bits<InputBits>(OutputValue(z));
53  x |= unbounded_shl<shift>(y);
54  }
55  };
56 
57  template<int UnitBits, int InputBits, int OutputBits, int k>
58  struct imploder_step<stream_endian::little_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
59  template<typename InputValue, typename OutputValue>
60  static void step(InputValue z, OutputValue &x) {
61  int const kb = (k % UnitBits);
62  int const ku = k - kb;
63  int const shift = InputBits >= UnitBits ? k : OutputBits >= UnitBits ? ku + (UnitBits -
64  (InputBits + kb)) : OutputBits - (InputBits + kb);
65  OutputValue y = low_bits<InputBits>(OutputValue(z));
66  x |= unbounded_shl<shift>(y);
67  }
68  };
69 
70  template<int UnitBits, int InputBits, int OutputBits, int k>
71  struct imploder_step<stream_endian::big_unit_little_bit < UnitBits>, InputBits, OutputBits, k> {
72  template<typename InputValue, typename OutputValue>
73  static void step(InputValue z, OutputValue &x) {
74  int const kb = (k % UnitBits);
75  int const ku = k - kb;
76  int const shift = InputBits >= UnitBits ? OutputBits - (InputBits + k) : OutputBits >=
77  UnitBits ? OutputBits - (UnitBits + ku) + kb : kb;
78  OutputValue y = low_bits<InputBits>(OutputValue(z));
79  x |= unbounded_shl<shift>(y);
80  }
81  };
82 
83  template<int UnitBits, int InputBits, int OutputBits, int k>
84  struct imploder_step<stream_endian::little_unit_little_bit < UnitBits>, InputBits, OutputBits, k> {
85  template<typename InputValue, typename OutputValue>
86  static void step(InputValue z, OutputValue &x) {
87  int const shift = k;
88  OutputValue y = low_bits<InputBits>(OutputValue(z));
89  x |= unbounded_shl<shift>(y);
90  }
91  };
92 
93  template<int UnitBits, int InputBits, int OutputBits, int k>
94  struct imploder_step<stream_endian::host_unit < UnitBits>, InputBits, OutputBits, k> {
95  template<typename InputValue, typename OutputValue>
96  static void step(InputValue z, OutputValue &x) {
97  BOOST_STATIC_ASSERT(sizeof(InputValue) * CHAR_BIT == InputBits);
98  BOOST_STATIC_ASSERT(sizeof(OutputValue) * CHAR_BIT == OutputBits);
99  std::memcpy((char *) &x + k / CHAR_BIT, &z, InputBits / CHAR_BIT);
100  }
101  };
102 
103  template<typename Endianness, int InputBits, int OutputBits, int k = 0>
104  struct imploder;
105 
106  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits, int k>
107  struct imploder<Endian<UnitBits>, InputBits, OutputBits, k> {
108 
109  // To keep the implementation managable, input and output sizes must
110  // be multiples or factors of the unit size.
111  // If one of these is firing, you may want a bit-only stream_endian
112  // rather than one that mentions bytes or octets.
113  BOOST_STATIC_ASSERT(!(InputBits % UnitBits && UnitBits % InputBits));
114  BOOST_STATIC_ASSERT(!(OutputBits % UnitBits && UnitBits % OutputBits));
115 
116  typedef Endian<UnitBits> Endianness;
119 
120  template<typename InIter, typename OutputValue>
121  static void implode(InIter &in, OutputValue &x) {
122  step_type::step(*in++, x);
123  next_type::implode(in, x);
124  }
125  };
126 
127  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits>
128  struct imploder<Endian<UnitBits>, InputBits, OutputBits, OutputBits> {
129  template<typename InIter, typename OutputValue>
130  static void implode(InIter &, OutputValue &) {
131 
132  }
133  };
134  } // namespace detail
135  }
136 } // namespace nil
137 // @formatter:on
138 
139 #endif // CRYPTO3_CODEC_DETAIL_IMPLODER_HPP
Definition: pair.hpp:31
static void implode(InIter &in, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:121
BOOST_STATIC_ASSERT(!(OutputBits % UnitBits &&UnitBits % OutputBits))
imploder_step< Endianness, InputBits, OutputBits, k > step_type
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:117
BOOST_STATIC_ASSERT(!(InputBits % UnitBits &&UnitBits % InputBits))
imploder< Endianness, InputBits, OutputBits, k+InputBits > next_type
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:118
Endian< UnitBits > Endianness
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:116
static void implode(InIter &, OutputValue &)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:130
static void step(InputValue z, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:50
static void step(InputValue z, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:73
static void step(InputValue z, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:96
static void step(InputValue z, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:60
static void step(InputValue z, OutputValue &x)
Definition: passhash/include/nil/crypto3/detail/imploder.hpp:86
imploder_step packs an input value represented in InputEndianness endianness into an output value rep...
Definition: block/include/nil/crypto3/detail/imploder.hpp:93
constexpr static int const shift
Definition: block/include/nil/crypto3/detail/imploder.hpp:94
imploder processes a sequence of input values represented in InputEndianness endianness into an outpu...
Definition: block/include/nil/crypto3/detail/imploder.hpp:122