1#ifndef ANDROID_PDX_RPC_TYPE_OPERATORS_H_ 2#define ANDROID_PDX_RPC_TYPE_OPERATORS_H_ 3 4#include <array> 5#include <map> 6#include <type_traits> 7#include <unordered_map> 8#include <vector> 9 10#include <pdx/channel_handle.h> 11#include <pdx/file_handle.h> 12#include <pdx/rpc/array_wrapper.h> 13#include <pdx/rpc/buffer_wrapper.h> 14#include <pdx/rpc/copy_cv_reference.h> 15#include <pdx/rpc/pointer_wrapper.h> 16#include <pdx/rpc/string_wrapper.h> 17 18namespace android { 19namespace pdx { 20namespace rpc { 21 22// Simplifies type expressions. 23template <typename T> 24using Decay = typename std::decay<T>::type; 25 26// Compares the underlying type of A and B. 27template <typename A, typename B> 28using IsEquivalent = typename std::is_same<Decay<A>, Decay<B>>::type; 29 30// Logical AND over template parameter pack. 31template <typename... T> 32struct And : std::false_type {}; 33template <typename A, typename B> 34struct And<A, B> : std::integral_constant<bool, A::value && B::value> {}; 35template <typename A, typename B, typename... Rest> 36struct And<A, B, Rest...> : And<A, And<B, Rest...>> {}; 37 38// Determines whether A is convertible to B (serializes to the same format) 39// using these rules: 40// 1. std:vector<T, Any...> is convertible to ArrayWrapper<T>. 41// 2. ArrayWrapper<T> is convertible to std:vector<T, Any...>. 42// 3. std::basic_string<T, Any...> is convertible to StringWrapper<T>. 43// 4. StringWrapper<T> is convertible to std::basic_string<T, Any...>. 44// 5. BufferWrapper<T*> is convertible to BufferWrapper<std::vector<T, 45// Any...>>. 46// 6. BufferWrapper<std::vector<T, ...>> is convertible to BufferWrapper<T*>. 47// 7. The value type T of A and B must match. 48 49// Compares A and B for convertibility. This base type determines convertibility 50// by equivalence of the underlying types of A and B. Specializations of this 51// type handle the rules for which complex types are convertible. 52template <typename A, typename B> 53struct IsConvertible : IsEquivalent<A, B> {}; 54 55// Compares TT<A, ...> and TT<B, ...>; these are convertible if A and B are 56// convertible. 57template <template <typename, typename...> class TT, typename A, typename B, 58 typename... AnyA, typename... AnyB> 59struct IsConvertible<TT<A, AnyA...>, TT<B, AnyB...>> 60 : IsConvertible<Decay<A>, Decay<B>> {}; 61 62// Compares TT<KeyA, ValueA, ...> and TT<KeyB, ValueB, ...>; these are 63// convertible if KeyA and KeyB are 64// convertible and ValueA and ValueB are convertible. 65template <template <typename, typename, typename...> class TT, typename KeyA, 66 typename ValueA, typename KeyB, typename ValueB, typename... AnyA, 67 typename... AnyB> 68struct IsConvertible<TT<KeyA, ValueA, AnyA...>, TT<KeyB, ValueB, AnyB...>> 69 : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, 70 IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; 71 72// Compares two std::pairs to see if the corresponding elements are convertible. 73template <typename A, typename B, typename C, typename D> 74struct IsConvertible<std::pair<A, B>, std::pair<C, D>> 75 : And<IsConvertible<Decay<A>, Decay<C>>, 76 IsConvertible<Decay<B>, Decay<D>>> {}; 77 78// Compares std::pair with a two-element std::tuple to see if the corresponding 79// elements are convertible. 80template <typename A, typename B, typename C, typename D> 81struct IsConvertible<std::pair<A, B>, std::tuple<C, D>> 82 : And<IsConvertible<Decay<A>, Decay<C>>, 83 IsConvertible<Decay<B>, Decay<D>>> {}; 84template <typename A, typename B, typename C, typename D> 85struct IsConvertible<std::tuple<A, B>, std::pair<C, D>> 86 : And<IsConvertible<Decay<A>, Decay<C>>, 87 IsConvertible<Decay<B>, Decay<D>>> {}; 88 89// Compares two std::tuples to see if the corresponding elements are 90// convertible. 91template <typename... A, typename... B> 92struct IsConvertible<std::tuple<A...>, std::tuple<B...>> 93 : And<IsConvertible<Decay<A>, Decay<B>>...> {}; 94 95// Compares std::vector, std::array, and ArrayWrapper; these are convertible if 96// the value types are convertible. 97template <typename A, typename B, typename... Any> 98struct IsConvertible<std::vector<A, Any...>, ArrayWrapper<B>> 99 : IsConvertible<Decay<A>, Decay<B>> {}; 100template <typename A, typename B, typename... Any> 101struct IsConvertible<ArrayWrapper<A>, std::vector<B, Any...>> 102 : IsConvertible<Decay<A>, Decay<B>> {}; 103template <typename A, typename B, typename... Any, std::size_t Size> 104struct IsConvertible<std::vector<A, Any...>, std::array<B, Size>> 105 : IsConvertible<Decay<A>, Decay<B>> {}; 106template <typename A, typename B, typename... Any, std::size_t Size> 107struct IsConvertible<std::array<A, Size>, std::vector<B, Any...>> 108 : IsConvertible<Decay<A>, Decay<B>> {}; 109template <typename A, typename B, std::size_t Size> 110struct IsConvertible<ArrayWrapper<A>, std::array<B, Size>> 111 : IsConvertible<Decay<A>, Decay<B>> {}; 112template <typename A, typename B, std::size_t Size> 113struct IsConvertible<std::array<A, Size>, ArrayWrapper<B>> 114 : IsConvertible<Decay<A>, Decay<B>> {}; 115 116// Compares std::map and std::unordered_map; these are convertible if the keys 117// are convertible and the values are convertible. 118template <typename KeyA, typename ValueA, typename KeyB, typename ValueB, 119 typename... AnyA, typename... AnyB> 120struct IsConvertible<std::map<KeyA, ValueA, AnyA...>, 121 std::unordered_map<KeyB, ValueB, AnyB...>> 122 : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, 123 IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; 124template <typename KeyA, typename ValueA, typename KeyB, typename ValueB, 125 typename... AnyA, typename... AnyB> 126struct IsConvertible<std::unordered_map<KeyA, ValueA, AnyA...>, 127 std::map<KeyB, ValueB, AnyB...>> 128 : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, 129 IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; 130 131// Compares BufferWrapper<A*> and BufferWrapper<std::vector<B>>; these are 132// convertible if A and B are equivalent. Allocator types are not relevant to 133// convertibility. 134template <typename A, typename B, typename Allocator> 135struct IsConvertible<BufferWrapper<A*>, 136 BufferWrapper<std::vector<B, Allocator>>> 137 : IsEquivalent<A, B> {}; 138template <typename A, typename B, typename Allocator> 139struct IsConvertible<BufferWrapper<std::vector<A, Allocator>>, 140 BufferWrapper<B*>> : IsEquivalent<A, B> {}; 141template <typename A, typename B, typename AllocatorA, typename AllocatorB> 142struct IsConvertible<BufferWrapper<std::vector<A, AllocatorA>>, 143 BufferWrapper<std::vector<B, AllocatorB>>> 144 : IsEquivalent<A, B> {}; 145template <typename A, typename B> 146struct IsConvertible<BufferWrapper<A*>, BufferWrapper<B*>> 147 : IsEquivalent<A, B> {}; 148 149// Compares std::basic_string<A, ...> and StringWrapper<B>; these are 150// convertible if A and B are equivalent. 151template <typename A, typename B, typename... Any> 152struct IsConvertible<std::basic_string<A, Any...>, StringWrapper<B>> 153 : IsEquivalent<A, B> {}; 154template <typename A, typename B, typename... Any> 155struct IsConvertible<StringWrapper<A>, std::basic_string<B, Any...>> 156 : IsEquivalent<A, B> {}; 157 158// Compares PointerWrapper<A> and B; these are convertible if A and B are 159// convertible. 160template <typename A, typename B> 161struct IsConvertible<PointerWrapper<A>, B> : IsConvertible<Decay<A>, Decay<B>> { 162}; 163template <typename A, typename B> 164struct IsConvertible<A, PointerWrapper<B>> : IsConvertible<Decay<A>, Decay<B>> { 165}; 166 167// LocalHandle is convertible to RemoteHandle on the service side. This means 168// that a RemoteHandle may be supplied by a service when the protocol calls for 169// a LocalHandle return value. The other way around is not safe and can leak 170// file descriptors. The ServicePayload class enforces this policy by only 171// supporting RemoteHandle for pushed handles. 172template <> 173struct IsConvertible<LocalHandle, RemoteHandle> : std::true_type {}; 174template <> 175struct IsConvertible<LocalHandle, BorrowedHandle> : std::true_type {}; 176 177template <> 178struct IsConvertible<LocalChannelHandle, RemoteChannelHandle> : std::true_type { 179}; 180template <> 181struct IsConvertible<LocalChannelHandle, BorrowedChannelHandle> 182 : std::true_type {}; 183 184// Conditionally "rewrites" type A as type B, including cv-reference qualifiers, 185// iff A is convertible to B. 186template <typename A, typename B> 187using ConditionalRewrite = 188 typename std::conditional<IsConvertible<Decay<A>, Decay<B>>::value, 189 CopyCVReferenceType<A, B>, A>::type; 190 191} // namespace rpc 192} // namespace pdx 193} // namespace android 194 195#endif // ANDROID_PDX_RPC_TYPE_OPERATORS_H_ 196