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 18namespace mojo { 19namespace internal { 20 21template <typename T> 22struct 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 33template < 34 typename Traits, 35 typename UserType, 36 typename std::enable_if<HasIsNullMethod<Traits>::value>::type* = nullptr> 37bool CallIsNullIfExists(const UserType& input) { 38 return Traits::IsNull(input); 39} 40 41template < 42 typename Traits, 43 typename UserType, 44 typename std::enable_if<!HasIsNullMethod<Traits>::value>::type* = nullptr> 45bool CallIsNullIfExists(const UserType& input) { 46 return false; 47} 48template <typename T> 49struct 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 60template < 61 typename Traits, 62 typename UserType, 63 typename std::enable_if<HasSetToNullMethod<Traits>::value>::type* = nullptr> 64bool CallSetToNullIfExists(UserType* output) { 65 Traits::SetToNull(output); 66 return true; 67} 68 69template <typename Traits, 70 typename UserType, 71 typename std::enable_if<!HasSetToNullMethod<Traits>::value>::type* = 72 nullptr> 73bool 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 80template <typename T> 81struct 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 92template <typename Traits, 93 bool has_context = HasSetUpContextMethod<Traits>::value> 94struct CustomContextHelper; 95 96template <typename Traits> 97struct 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 119template <typename Traits> 120struct 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 134template <typename ReturnType, typename ParamType, typename InputUserType> 135ReturnType CallWithContext(ReturnType (*f)(ParamType, void*), 136 InputUserType&& input, 137 void* context) { 138 return f(std::forward<InputUserType>(input), context); 139} 140 141template <typename ReturnType, typename ParamType, typename InputUserType> 142ReturnType CallWithContext(ReturnType (*f)(ParamType), 143 InputUserType&& input, 144 void* context) { 145 return f(std::forward<InputUserType>(input)); 146} 147 148template <typename T, typename MaybeConstUserType> 149struct 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 160template < 161 typename Traits, 162 typename MaybeConstUserType, 163 typename std::enable_if< 164 HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> 165decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>())) 166CallGetBeginIfExists(MaybeConstUserType& input) { 167 return Traits::GetBegin(input); 168} 169 170template < 171 typename Traits, 172 typename MaybeConstUserType, 173 typename std::enable_if< 174 !HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> 175size_t CallGetBeginIfExists(MaybeConstUserType& input) { 176 return 0; 177} 178 179template <typename T, typename MaybeConstUserType> 180struct 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 191template < 192 typename Traits, 193 typename MaybeConstUserType, 194 typename std::enable_if< 195 HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> 196decltype(Traits::GetData(std::declval<MaybeConstUserType&>())) 197CallGetDataIfExists(MaybeConstUserType& input) { 198 return Traits::GetData(input); 199} 200 201template < 202 typename Traits, 203 typename MaybeConstUserType, 204 typename std::enable_if< 205 !HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> 206void* 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