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 void* custom_context = Traits::SetUpContext(input);
101 if (!context->custom_contexts)
102 context->custom_contexts.reset(new std::queue<void*>());
103 context->custom_contexts->push(custom_context);
104 return custom_context;
105 }
106
107 static void* GetNext(SerializationContext* context) {
108 void* custom_context = context->custom_contexts->front();
109 context->custom_contexts->pop();
110 return custom_context;
111 }
112
113 template <typename MaybeConstUserType>
114 static void TearDown(MaybeConstUserType& input, void* custom_context) {
115 Traits::TearDownContext(input, custom_context);
116 }
117 };
118
119 template <typename Traits>
120 struct CustomContextHelper<Traits, false> {
121 template <typename MaybeConstUserType>
122 static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
123 return nullptr;
124 }
125
126 static void* GetNext(SerializationContext* context) { return nullptr; }
127
128 template <typename MaybeConstUserType>
129 static void TearDown(MaybeConstUserType& input, void* custom_context) {
130 DCHECK(!custom_context);
131 }
132 };
133
134 template <typename ReturnType, typename ParamType, typename InputUserType>
135 ReturnType CallWithContext(ReturnType (*f)(ParamType, void*),
136 InputUserType&& input,
137 void* context) {
138 return f(std::forward<InputUserType>(input), context);
139 }
140
141 template <typename ReturnType, typename ParamType, typename InputUserType>
142 ReturnType CallWithContext(ReturnType (*f)(ParamType),
143 InputUserType&& input,
144 void* context) {
145 return f(std::forward<InputUserType>(input));
146 }
147
148 template <typename T, typename MaybeConstUserType>
149 struct HasGetBeginMethod {
150 template <typename U>
151 static char Test(decltype(U::GetBegin(std::declval<MaybeConstUserType&>()))*);
152 template <typename U>
153 static int Test(...);
154 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
155
156 private:
157 EnsureTypeIsComplete<T> check_t_;
158 };
159
160 template <
161 typename Traits,
162 typename MaybeConstUserType,
163 typename std::enable_if<
164 HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
165 decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>()))
166 CallGetBeginIfExists(MaybeConstUserType& input) {
167 return Traits::GetBegin(input);
168 }
169
170 template <
171 typename Traits,
172 typename MaybeConstUserType,
173 typename std::enable_if<
174 !HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
175 size_t CallGetBeginIfExists(MaybeConstUserType& input) {
176 return 0;
177 }
178
179 template <typename T, typename MaybeConstUserType>
180 struct HasGetDataMethod {
181 template <typename U>
182 static char Test(decltype(U::GetData(std::declval<MaybeConstUserType&>()))*);
183 template <typename U>
184 static int Test(...);
185 static const bool value = sizeof(Test<T>(0)) == sizeof(char);
186
187 private:
188 EnsureTypeIsComplete<T> check_t_;
189 };
190
191 template <
192 typename Traits,
193 typename MaybeConstUserType,
194 typename std::enable_if<
195 HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
196 decltype(Traits::GetData(std::declval<MaybeConstUserType&>()))
197 CallGetDataIfExists(MaybeConstUserType& input) {
198 return Traits::GetData(input);
199 }
200
201 template <
202 typename Traits,
203 typename MaybeConstUserType,
204 typename std::enable_if<
205 !HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
206 void* CallGetDataIfExists(MaybeConstUserType& input) {
207 return nullptr;
208 }
209
210 } // namespace internal
211 } // namespace mojo
212
213 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
214