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