blob: a3f306f540112c83812c399dbcb6c9073bd76b13 [file] [log] [blame]
Vernon Mauerye7329c72018-10-08 12:05:16 -07001/**
2 * Copyright © 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17#include <boost/asio/spawn.hpp>
18#include <boost/callable_traits.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050019
Vernon Mauerye7329c72018-10-08 12:05:16 -070020#include <cstdint>
21#include <map>
22#include <memory>
23#include <string>
24#include <tuple>
25#include <type_traits>
26#include <vector>
27
28namespace ipmi
29{
30
Vernon Maueryded4c742019-04-02 16:26:11 -070031// forward declare Context and Request for NonIpmiArgsCount
Vernon Mauerye7329c72018-10-08 12:05:16 -070032struct Context;
Vernon Maueryded4c742019-04-02 16:26:11 -070033namespace message
34{
35struct Request;
36}
Vernon Mauerye7329c72018-10-08 12:05:16 -070037
38namespace utility
39{
40
41/**
42 * @brief a utility template to extract the args after N from a tuple
43 *
44 * Given a tuple of type <T1, ...TN, TN+1, ...>, provide type = tuple<TN+1,...>
45 */
46template <std::size_t N, typename FirstArg, typename... Rest>
47struct StripFirstArgs;
48
49template <std::size_t N, typename FirstArg, typename... Rest>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050050struct StripFirstArgs<N, std::tuple<FirstArg, Rest...>> :
51 StripFirstArgs<N - 1, std::tuple<Rest...>>
52{};
Vernon Mauerye7329c72018-10-08 12:05:16 -070053
54template <typename FirstArg, typename... Rest>
55struct StripFirstArgs<0, std::tuple<FirstArg, Rest...>>
56{
57 using type = std::tuple<FirstArg, Rest...>;
58};
59template <std::size_t N>
60struct StripFirstArgs<N, std::tuple<>>
61{
62 using type = std::tuple<>;
63};
64
65/**
66 * @brief a utility template to extract the remaining args from a tuple
67 *
68 * Given a tuple of type <T1, T2,...>, provide type = tuple<T2,...>
69 */
70template <typename T>
71using StripFirstArg = StripFirstArgs<1, T>;
72
73/**
74 * @brief a utility template to find the number of non-special arguments
75 *
76 * Given a tuple, count the args after the first special args
77 */
78template <typename FirstArg, typename... Rest>
79struct NonIpmiArgsCount;
80
81template <>
82struct NonIpmiArgsCount<std::tuple<>>
83{
84 constexpr static std::size_t size()
85 {
86 return 0;
87 }
88};
89template <typename FirstArg, typename... OtherArgs>
90struct NonIpmiArgsCount<std::tuple<FirstArg, OtherArgs...>>
91{
92 constexpr static std::size_t size()
93 {
Vernon Maueryded4c742019-04-02 16:26:11 -070094 if constexpr (std::is_same<
95 FirstArg,
96 std::shared_ptr<ipmi::message::Request>>::value ||
97 std::is_same<FirstArg,
98 std::shared_ptr<ipmi::Context>>::value ||
Vernon Mauerye7329c72018-10-08 12:05:16 -070099 std::is_same<FirstArg, boost::asio::yield_context>::value)
100 {
101 return 1 + NonIpmiArgsCount<std::tuple<OtherArgs...>>::size();
102 }
103 else
104 {
105 return NonIpmiArgsCount<std::tuple<OtherArgs...>>::size();
106 }
107 }
108};
109
110/**
111 * @brief a utility template to find the type of the first arg
112 *
113 * Given a tuple, provide the type of the first element
114 */
115template <typename T>
116struct GetFirstArg
117{
118 using type = void;
119};
120
121template <typename FirstArg, typename... Rest>
122struct GetFirstArg<std::tuple<FirstArg, Rest...>>
123{
124 using type = FirstArg;
125};
126
127/**
128 * @brief a utility template to remove const and reference from types
129 *
130 * Given a tuple, provide the type of the first element
131 */
132template <typename... Args>
133struct DecayTuple;
134
135template <typename... Args>
136struct DecayTuple<std::tuple<Args...>>
137{
138 using type = std::tuple<typename std::decay<Args>::type...>;
139};
140
141/** @brief Convert T[N] to T* if is_same<Tbase,T>
142 *
143 * @tparam Tbase - The base type expected.
144 * @tparam T - The type to convert.
145 */
146template <typename Tbase, typename T>
147using ArrayToPtr_t = typename std::conditional_t<
148 std::is_array<T>::value,
149 std::conditional_t<std::is_same<Tbase, std::remove_extent_t<T>>::value,
150 std::add_pointer_t<std::remove_extent_t<T>>, T>,
151 T>;
152
153/** @brief Downcast type submembers.
154 *
155 * This allows std::tuple and std::pair members to be downcast to their
156 * non-const, nonref versions of themselves to limit duplication in template
157 * specializations
158 *
159 * 1. Remove references.
160 * 2. Remove 'const' and 'volatile'.
161 * 3. Convert 'char[N]' to 'char*'.
162 */
163template <typename T>
164struct DowncastMembers
165{
166 using type = T;
167};
168template <typename... Args>
169struct DowncastMembers<std::pair<Args...>>
170{
171 using type = std::pair<utility::ArrayToPtr_t<
172 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>;
173};
174
175template <typename... Args>
176struct DowncastMembers<std::tuple<Args...>>
177{
178 using type = std::tuple<utility::ArrayToPtr_t<
179 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>;
180};
181
182template <typename T>
183using DowncastMembers_t = typename DowncastMembers<T>::type;
184
185/** @brief Convert some C++ types to others for 'TypeId' conversion purposes.
186 *
187 * Similar C++ types have the same dbus type-id, so 'downcast' those to limit
188 * duplication in TypeId template specializations.
189 *
190 * 1. Remove references.
191 * 2. Remove 'const' and 'volatile'.
192 * 3. Convert 'char[N]' to 'char*'.
193 */
194template <typename T>
195struct TypeIdDowncast
196{
197 using type = utility::ArrayToPtr_t<
198 char, DowncastMembers_t<std::remove_cv_t<std::remove_reference_t<T>>>>;
199};
200
201template <typename T>
202using TypeIdDowncast_t = typename TypeIdDowncast<T>::type;
203
204/** @brief Detect if a type is a tuple
205 *
206 */
207template <typename>
208struct is_tuple : std::false_type
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500209{};
Vernon Mauerye7329c72018-10-08 12:05:16 -0700210
211template <typename... T>
212struct is_tuple<std::tuple<T...>> : std::true_type
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500213{};
Vernon Mauerye7329c72018-10-08 12:05:16 -0700214
Vernon Mauerya3dd7662019-05-30 15:20:52 -0700215/** @brief used for static_assert in a constexpr-if else statement
216 */
217template <typename T>
218struct dependent_false : std::false_type
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500219{};
Vernon Mauerya3dd7662019-05-30 15:20:52 -0700220
Vernon Mauerye7329c72018-10-08 12:05:16 -0700221} // namespace utility
222
223} // namespace ipmi