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