stream/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 
43  template<typename Endianness, int InputBits, int OutputBits, int k>
44  struct imploder_step;
45 
46  template<int UnitBits, int InputBits, int OutputBits, int k>
47  struct imploder_step<stream_endian::big_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
48  template<typename InputValue, typename OutputValue>
49  static void step(InputValue z, OutputValue &x) {
50  int const shift = OutputBits - (InputBits + k);
51  OutputValue y = low_bits<InputBits>(OutputValue(z));
52  x |= unbounded_shl<shift>(y);
53  }
54  };
55 
56  template<int UnitBits, int InputBits, int OutputBits, int k>
57  struct imploder_step<stream_endian::little_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
58  template<typename InputValue, typename OutputValue>
59  static void step(InputValue z, OutputValue &x) {
60  int const kb = (k % UnitBits);
61  int const ku = k - kb;
62  int const shift =
63  InputBits >= UnitBits ?
64  k :
65  OutputBits >= UnitBits ? ku + (UnitBits - (InputBits + kb)) : OutputBits - (InputBits + kb);
66  OutputValue y = low_bits<InputBits>(OutputValue(z));
67  x |= unbounded_shl<shift>(y);
68  }
69  };
70 
71  template<int UnitBits, int InputBits, int OutputBits, int k>
72  struct imploder_step<stream_endian::big_unit_little_bit<UnitBits>, InputBits, OutputBits, k> {
73  template<typename InputValue, typename OutputValue>
74  static void step(InputValue z, OutputValue &x) {
75  int const kb = (k % UnitBits);
76  int const ku = k - kb;
77  int const shift = InputBits >= UnitBits ?
78  OutputBits - (InputBits + k) :
79  OutputBits >= UnitBits ? OutputBits - (UnitBits + ku) + kb : kb;
80  OutputValue y = low_bits<InputBits>(OutputValue(z));
81  x |= unbounded_shl<shift>(y);
82  }
83  };
84 
85  template<int UnitBits, int InputBits, int OutputBits, int k>
86  struct imploder_step<stream_endian::little_unit_little_bit<UnitBits>, InputBits, OutputBits, k> {
87  template<typename InputValue, typename OutputValue>
88  static void step(InputValue z, OutputValue &x) {
89  int const shift = k;
90  OutputValue y = low_bits<InputBits>(OutputValue(z));
91  x |= unbounded_shl<shift>(y);
92  }
93  };
94 
95  template<int UnitBits, int InputBits, int OutputBits, int k>
96  struct imploder_step<stream_endian::host_unit<UnitBits>, InputBits, OutputBits, k> {
97  template<typename InputValue, typename OutputValue>
98  static void step(InputValue z, OutputValue &x) {
99  BOOST_STATIC_ASSERT(sizeof(InputValue) * CHAR_BIT == InputBits);
100  BOOST_STATIC_ASSERT(sizeof(OutputValue) * CHAR_BIT == OutputBits);
101  std::memcpy((char *)&x + k / CHAR_BIT, &z, InputBits / CHAR_BIT);
102  }
103  };
104 
105  template<typename Endianness, int InputBits, int OutputBits, int k = 0>
106  struct imploder;
107 
108  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits, int k>
109  struct imploder<Endian<UnitBits>, InputBits, OutputBits, k> {
110 
111  // To keep the implementation managable, input and output sizes must
112  // be multiples or factors of the unit size.
113  // If one of these is firing, you may want a bit-only stream_endian
114  // rather than one that mentions bytes or octets.
115  BOOST_STATIC_ASSERT(!(InputBits % UnitBits && UnitBits % InputBits));
116  BOOST_STATIC_ASSERT(!(OutputBits % UnitBits && UnitBits % OutputBits));
117 
118  typedef Endian<UnitBits> Endianness;
121 
122  template<typename InIter, typename OutputValue>
123  static void implode(InIter &in, OutputValue &x) {
124  step_type::step(*in++, x);
125  next_type::implode(in, x);
126  }
127  };
128 
129  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits>
130  struct imploder<Endian<UnitBits>, InputBits, OutputBits, OutputBits> {
131  template<typename InIter, typename OutputValue>
132  static void implode(InIter &, OutputValue &) {
133  }
134  };
135 
136  } // namespace detail
137  } // namespace crypto3
138 } // namespace nil
139 
140 #endif // CRYPTO3_BLOCK_DETAIL_IMPLODER_HPP
Definition: pair.hpp:31
static void implode(InIter &in, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:123
BOOST_STATIC_ASSERT(!(OutputBits % UnitBits &&UnitBits % OutputBits))
imploder_step< Endianness, InputBits, OutputBits, k > step_type
Definition: stream/include/nil/crypto3/detail/imploder.hpp:119
BOOST_STATIC_ASSERT(!(InputBits % UnitBits &&UnitBits % InputBits))
imploder< Endianness, InputBits, OutputBits, k+InputBits > next_type
Definition: stream/include/nil/crypto3/detail/imploder.hpp:120
Endian< UnitBits > Endianness
Definition: stream/include/nil/crypto3/detail/imploder.hpp:118
static void implode(InIter &, OutputValue &)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:132
static void step(InputValue z, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:49
static void step(InputValue z, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:74
static void step(InputValue z, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:98
static void step(InputValue z, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:59
static void step(InputValue z, OutputValue &x)
Definition: stream/include/nil/crypto3/detail/imploder.hpp:88
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