1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <queue>
12
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
16 #include "mojo/public/cpp/bindings/lib/serialization_context.h"
17
18 namespace mojo {
19 namespace internal {
20
21 template <typename T>
22 struct HasIsNullMethod {
23 template <typename U>
24 static char Test(decltype(U::IsNull) *);
25 template <typename U>
26 static int Test(...);
27 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
28
29 private:
30 EnsureTypeIsComplete<T> check_t_;
31 };
32
33 template <
34 typename Traits,
35 typename UserType,
36 typename std::enable_if<HasIsNullMethod<Traits>::value>::type* = nullptr>
CallIsNullIfExists(const UserType & input)37 bool CallIsNullIfExists(const UserType& input) {
38 return Traits::IsNull(input);
39 }
40
41 template <
42 typename Traits,
43 typename UserType,
44 typename std::enable_if<!HasIsNullMethod<Traits>::value>::type* = nullptr>
CallIsNullIfExists(const UserType & input)45 bool CallIsNullIfExists(const UserType& input) {
46 return false;
47 }
48 template <typename T>
49 struct HasSetToNullMethod {
50 template <typename U>
51 static char Test(decltype(U::SetToNull) *);
52 template <typename U>
53 static int Test(...);
54 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
55
56 private:
57 EnsureTypeIsComplete<T> check_t_;
58 };
59
60 template <
61 typename Traits,
62 typename UserType,
63 typename std::enable_if<HasSetToNullMethod<Traits>::value>::type* = nullptr>
CallSetToNullIfExists(UserType * output)64 bool CallSetToNullIfExists(UserType* output) {
65 Traits::SetToNull(output);
66 return true;
67 }
68
69 template <typename Traits,
70 typename UserType,
71 typename std::enable_if<!HasSetToNullMethod<Traits>::value>::type* =
72 nullptr>
CallSetToNullIfExists(UserType * output)73 bool CallSetToNullIfExists(UserType* output) {
74 LOG(ERROR) << "A null value is received. But the Struct/Array/StringTraits "
75 << "class doesn't define a SetToNull() function and therefore is "
76 << "unable to deserialize the value.";
77 return false;
78 }
79
80 template <typename T>
81 struct HasSetUpContextMethod {
82 template <typename U>
83 static char Test(decltype(U::SetUpContext) *);
84 template <typename U>
85 static int Test(...);
86 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
87
88 private:
89 EnsureTypeIsComplete<T> check_t_;
90 };
91
92 template <typename Traits,
93 bool has_context = HasSetUpContextMethod<Traits>::value>
94 struct CustomContextHelper;
95
96 template <typename Traits>
97 struct CustomContextHelper<Traits, true> {
98 template <typename MaybeConstUserType>
99 static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
100 return Traits::SetUpContext(input);
101 }
102
103 template <typename MaybeConstUserType>
104 static void TearDown(MaybeConstUserType& input, void* custom_context) {
105 Traits::TearDownContext(input, custom_context);
106 }
107 };
108
109 template <typename Traits>
110 struct CustomContextHelper<Traits, false> {
111 template <typename MaybeConstUserType>
112 static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
113 return nullptr;
114 }
115
116 template <typename MaybeConstUserType>
117 static void TearDown(MaybeConstUserType& input, void* custom_context) {
118 DCHECK(!custom_context);
119 }
120 };
121
122 template <typename ReturnType, typename ParamType, typename InputUserType>
123 ReturnType CallWithContext(ReturnType (*f)(ParamType, void*),
124 InputUserType&& input,
125 void* context) {
126 return f(std::forward<InputUserType>(input), context);
127 }
128
129 template <typename ReturnType, typename ParamType, typename InputUserType>
130 ReturnType CallWithContext(ReturnType (*f)(ParamType),
131 InputUserType&& input,
132 void* context) {
133 return f(std::forward<InputUserType>(input));
134 }
135
136 template <typename T, typename MaybeConstUserType>
137 struct HasGetBeginMethod {
138 template <typename U>
139 static char Test(
140 decltype(U::GetBegin(std::declval<MaybeConstUserType&>())) *);
141 template <typename U>
142 static int Test(...);
143 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
144
145 private:
146 EnsureTypeIsComplete<T> check_t_;
147 };
148
149 template <
150 typename Traits,
151 typename MaybeConstUserType,
152 typename std::enable_if<
153 HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
154 decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>()))
155 CallGetBeginIfExists(MaybeConstUserType& input) {
156 return Traits::GetBegin(input);
157 }
158
159 template <
160 typename Traits,
161 typename MaybeConstUserType,
162 typename std::enable_if<
163 !HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
164 size_t CallGetBeginIfExists(MaybeConstUserType& input) {
165 return 0;
166 }
167
168 template <typename T, typename MaybeConstUserType>
169 struct HasGetDataMethod {
170 template <typename U>
171 static char Test(decltype(U::GetData(std::declval<MaybeConstUserType&>())) *);
172 template <typename U>
173 static int Test(...);
174 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
175
176 private:
177 EnsureTypeIsComplete<T> check_t_;
178 };
179
180 template <
181 typename Traits,
182 typename MaybeConstUserType,
183 typename std::enable_if<
184 HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
185 decltype(Traits::GetData(std::declval<MaybeConstUserType&>()))
186 CallGetDataIfExists(MaybeConstUserType& input) {
187 return Traits::GetData(input);
188 }
189
190 template <
191 typename Traits,
192 typename MaybeConstUserType,
193 typename std::enable_if<
194 !HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
195 void* CallGetDataIfExists(MaybeConstUserType& input) {
196 return nullptr;
197 }
198
199 } // namespace internal
200 } // namespace mojo
201
202 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
203