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 
18 namespace android {
19 namespace pdx {
20 namespace rpc {
21 
22 // Simplifies type expressions.
23 template <typename T>
24 using Decay = typename std::decay<T>::type;
25 
26 // Compares the underlying type of A and B.
27 template <typename A, typename B>
28 using IsEquivalent = typename std::is_same<Decay<A>, Decay<B>>::type;
29 
30 // Logical AND over template parameter pack.
31 template <typename... T>
32 struct And : std::false_type {};
33 template <typename A, typename B>
34 struct And<A, B> : std::integral_constant<bool, A::value && B::value> {};
35 template <typename A, typename B, typename... Rest>
36 struct 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.
52 template <typename A, typename B>
53 struct IsConvertible : IsEquivalent<A, B> {};
54 
55 // Compares TT<A, ...> and TT<B, ...>; these are convertible if A and B are
56 // convertible.
57 template <template <typename, typename...> class TT, typename A, typename B,
58           typename... AnyA, typename... AnyB>
59 struct 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.
65 template <template <typename, typename, typename...> class TT, typename KeyA,
66           typename ValueA, typename KeyB, typename ValueB, typename... AnyA,
67           typename... AnyB>
68 struct 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.
73 template <typename A, typename B, typename C, typename D>
74 struct 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.
80 template <typename A, typename B, typename C, typename D>
81 struct IsConvertible<std::pair<A, B>, std::tuple<C, D>>
82     : And<IsConvertible<Decay<A>, Decay<C>>,
83           IsConvertible<Decay<B>, Decay<D>>> {};
84 template <typename A, typename B, typename C, typename D>
85 struct 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.
91 template <typename... A, typename... B>
92 struct 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.
97 template <typename A, typename B, typename... Any>
98 struct IsConvertible<std::vector<A, Any...>, ArrayWrapper<B>>
99     : IsConvertible<Decay<A>, Decay<B>> {};
100 template <typename A, typename B, typename... Any>
101 struct IsConvertible<ArrayWrapper<A>, std::vector<B, Any...>>
102     : IsConvertible<Decay<A>, Decay<B>> {};
103 template <typename A, typename B, typename... Any, std::size_t Size>
104 struct IsConvertible<std::vector<A, Any...>, std::array<B, Size>>
105     : IsConvertible<Decay<A>, Decay<B>> {};
106 template <typename A, typename B, typename... Any, std::size_t Size>
107 struct IsConvertible<std::array<A, Size>, std::vector<B, Any...>>
108     : IsConvertible<Decay<A>, Decay<B>> {};
109 template <typename A, typename B, std::size_t Size>
110 struct IsConvertible<ArrayWrapper<A>, std::array<B, Size>>
111     : IsConvertible<Decay<A>, Decay<B>> {};
112 template <typename A, typename B, std::size_t Size>
113 struct 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.
118 template <typename KeyA, typename ValueA, typename KeyB, typename ValueB,
119           typename... AnyA, typename... AnyB>
120 struct 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>>> {};
124 template <typename KeyA, typename ValueA, typename KeyB, typename ValueB,
125           typename... AnyA, typename... AnyB>
126 struct 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.
134 template <typename A, typename B, typename Allocator>
135 struct IsConvertible<BufferWrapper<A*>,
136                      BufferWrapper<std::vector<B, Allocator>>>
137     : IsEquivalent<A, B> {};
138 template <typename A, typename B, typename Allocator>
139 struct IsConvertible<BufferWrapper<std::vector<A, Allocator>>,
140                      BufferWrapper<B*>> : IsEquivalent<A, B> {};
141 template <typename A, typename B, typename AllocatorA, typename AllocatorB>
142 struct IsConvertible<BufferWrapper<std::vector<A, AllocatorA>>,
143                      BufferWrapper<std::vector<B, AllocatorB>>>
144     : IsEquivalent<A, B> {};
145 template <typename A, typename B>
146 struct 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.
151 template <typename A, typename B, typename... Any>
152 struct IsConvertible<std::basic_string<A, Any...>, StringWrapper<B>>
153     : IsEquivalent<A, B> {};
154 template <typename A, typename B, typename... Any>
155 struct 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.
160 template <typename A, typename B>
161 struct IsConvertible<PointerWrapper<A>, B> : IsConvertible<Decay<A>, Decay<B>> {
162 };
163 template <typename A, typename B>
164 struct 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.
172 template <>
173 struct IsConvertible<LocalHandle, RemoteHandle> : std::true_type {};
174 template <>
175 struct IsConvertible<LocalHandle, BorrowedHandle> : std::true_type {};
176 
177 template <>
178 struct IsConvertible<LocalChannelHandle, RemoteChannelHandle> : std::true_type {
179 };
180 template <>
181 struct 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.
186 template <typename A, typename B>
187 using 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