Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_POSTGRES_WSV_COMMON_HPP
7 : #define IROHA_POSTGRES_WSV_COMMON_HPP
8 :
9 : #include <soci/soci.h>
10 : #include <boost/optional.hpp>
11 : #include <boost/range/adaptor/filtered.hpp>
12 : #include <boost/range/adaptor/transformed.hpp>
13 : #include <boost/range/iterator_range.hpp>
14 : #include <boost/tuple/tuple.hpp>
15 : #include "common/bind.hpp"
16 :
17 : namespace iroha {
18 : namespace ametsuchi {
19 :
20 : template <typename ParamType, typename Function>
21 : inline void processSoci(soci::statement &st,
22 : soci::indicator &ind,
23 : ParamType &row,
24 : Function f) {
25 49 : while (st.fetch()) {
26 84 : switch (ind) {
27 : case soci::i_ok:
28 28 : f(row);
29 : case soci::i_null:
30 : case soci::i_truncated:
31 28 : break;
32 : }
33 : }
34 21 : }
35 :
36 : /// tuple length shortcut
37 : template <typename T>
38 : constexpr std::size_t length_v = boost::tuples::length<T>::value;
39 :
40 : /// tuple element type shortcut
41 : template <std::size_t N, typename T>
42 : using element_t = typename boost::tuples::element<N, T>::type;
43 :
44 : /// index sequence helper for concat
45 : template <class Tuple1, class Tuple2, std::size_t... Is, std::size_t... Js>
46 : auto concat_impl(std::index_sequence<Is...>, std::index_sequence<Js...>)
47 : -> boost::tuple<element_t<Is, std::decay_t<Tuple1>>...,
48 : element_t<Js, std::decay_t<Tuple2>>...>;
49 :
50 : /// tuple with types from two given tuples
51 : template <class Tuple1, class Tuple2>
52 : using concat = decltype(concat_impl<Tuple1, Tuple2>(
53 : std::make_index_sequence<length_v<std::decay_t<Tuple1>>>{},
54 : std::make_index_sequence<length_v<std::decay_t<Tuple2>>>{}));
55 :
56 : /// index sequence helper for index_apply
57 : template <typename F, std::size_t... Is>
58 : constexpr decltype(auto) index_apply_impl(F &&f,
59 : std::index_sequence<Is...>) {
60 4065 : return std::forward<F>(f)(std::integral_constant<std::size_t, Is>{}...);
61 : }
62 :
63 : /// apply F to an integer sequence [0, N)
64 : template <size_t N, typename F>
65 : constexpr decltype(auto) index_apply(F &&f) {
66 4065 : return index_apply_impl(std::forward<F>(f),
67 : std::make_index_sequence<N>{});
68 : }
69 :
70 : /// apply F to Tuple
71 : template <typename Tuple, typename F>
72 : constexpr decltype(auto) apply(Tuple &&t, F &&f) {
73 4065 : return index_apply<length_v<std::decay_t<Tuple>>>(
74 : [&](auto... Is) -> decltype(auto) {
75 4065 : return std::forward<F>(f)(
76 4065 : boost::get<Is>(std::forward<Tuple>(t))...);
77 : });
78 : }
79 :
80 : /// view first length_v<R> elements of T without copying
81 : template <typename R, typename T>
82 : constexpr auto viewQuery(T &&t) {
83 : return index_apply<length_v<std::decay_t<R>>>([&](auto... Is) {
84 157 : return boost::make_tuple(std::forward<T>(t).template get<Is>()...);
85 : });
86 : }
87 :
88 : /// view last length_v<R> elements of T without copying
89 : template <typename R, typename T>
90 : constexpr auto viewPermissions(T &&t) {
91 : return index_apply<length_v<std::decay_t<R>>>([&](auto... Is) {
92 55 : return boost::make_tuple(
93 55 : std::forward<T>(t)
94 55 : .template get<Is
95 : + length_v<std::decay_t<
96 : T>> - length_v<std::decay_t<R>>>()...);
97 : });
98 : }
99 :
100 : /// map tuple<optional<Ts>...> to optional<tuple<Ts...>>
101 : template <typename T>
102 : constexpr auto rebind(T &&t) {
103 : auto transform = [](auto &&... vals) {
104 154 : return boost::make_tuple(*std::forward<decltype(vals)>(vals)...);
105 : };
106 :
107 : using ReturnType =
108 : decltype(boost::make_optional(apply(std::forward<T>(t), transform)));
109 :
110 157 : return apply(std::forward<T>(t),
111 : [&](auto &&... vals) {
112 157 : bool temp[] = {static_cast<bool>(
113 157 : std::forward<decltype(vals)>(vals))...};
114 157 : return std::all_of(std::begin(temp),
115 157 : std::end(temp),
116 : [](auto b) { return b; });
117 : })
118 154 : ? boost::make_optional(apply(std::forward<T>(t), transform))
119 3 : : ReturnType{};
120 0 : }
121 :
122 : template <typename C, typename T, typename F>
123 : auto mapValues(T &t, F &&f) {
124 : return t | [&](auto &st) -> boost::optional<C> {
125 146 : return boost::copy_range<C>(
126 : st | boost::adaptors::transformed([&](auto &t) {
127 182 : return apply(t, std::forward<F>(f));
128 : }));
129 0 : };
130 : }
131 :
132 : template <typename C, typename T, typename F>
133 : auto flatMapValues(T &t, F &&f) {
134 : return t | [&](auto &st) -> boost::optional<C> {
135 1928 : return boost::copy_range<C>(
136 : st | boost::adaptors::transformed([&](auto &t) {
137 3908 : return apply(t, std::forward<F>(f));
138 : })
139 1928 : | boost::adaptors::filtered(
140 : [](auto &r) { return static_cast<bool>(r); })
141 : | boost::adaptors::transformed([](auto &&r) { return *r; }));
142 0 : };
143 : }
144 :
145 : template <typename T, typename F>
146 : auto flatMapValue(T &t, F &&f) {
147 : return t | [&](auto &st) -> decltype(
148 : apply(boost::make_iterator_range(st).front(),
149 : std::forward<F>(f))) {
150 29 : auto range = boost::make_iterator_range(st);
151 :
152 29 : if (range.empty()) {
153 3 : return boost::none;
154 : }
155 :
156 29 : return apply(range.front(), std::forward<F>(f));
157 29 : };
158 : }
159 :
160 : } // namespace ametsuchi
161 : } // namespace iroha
162 :
163 : #endif // IROHA_POSTGRES_WSV_COMMON_HPP
|