Home | History | Annotate | Download | only in lib
      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>
     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>
     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>
     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>
     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