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