blob: 4820a014ec182c21c14ead49534ff57374a6edcc [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_
#include <stddef.h>
#include <stdint.h>
#include <queue>
#include "base/logging.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
namespace mojo {
namespace internal {
template <typename T>
struct HasIsNullMethod {
template <typename U>
static char Test(decltype(U::IsNull)*);
template <typename U>
static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
private:
EnsureTypeIsComplete<T> check_t_;
};
template <
typename Traits,
typename UserType,
typename std::enable_if<HasIsNullMethod<Traits>::value>::type* = nullptr>
bool CallIsNullIfExists(const UserType& input) {
return Traits::IsNull(input);
}
template <
typename Traits,
typename UserType,
typename std::enable_if<!HasIsNullMethod<Traits>::value>::type* = nullptr>
bool CallIsNullIfExists(const UserType& input) {
return false;
}
template <typename T>
struct HasSetToNullMethod {
template <typename U>
static char Test(decltype(U::SetToNull)*);
template <typename U>
static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
private:
EnsureTypeIsComplete<T> check_t_;
};
template <
typename Traits,
typename UserType,
typename std::enable_if<HasSetToNullMethod<Traits>::value>::type* = nullptr>
bool CallSetToNullIfExists(UserType* output) {
Traits::SetToNull(output);
return true;
}
template <typename Traits,
typename UserType,
typename std::enable_if<!HasSetToNullMethod<Traits>::value>::type* =
nullptr>
bool CallSetToNullIfExists(UserType* output) {
LOG(ERROR) << "A null value is received. But the Struct/Array/StringTraits "
<< "class doesn't define a SetToNull() function and therefore is "
<< "unable to deserialize the value.";
return false;
}
template <typename T>
struct HasSetUpContextMethod {
template <typename U>
static char Test(decltype(U::SetUpContext)*);
template <typename U>
static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
private:
EnsureTypeIsComplete<T> check_t_;
};
template <typename Traits,
bool has_context = HasSetUpContextMethod<Traits>::value>
struct CustomContextHelper;
template <typename Traits>
struct CustomContextHelper<Traits, true> {
template <typename MaybeConstUserType>
static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
void* custom_context = Traits::SetUpContext(input);
if (!context->custom_contexts)
context->custom_contexts.reset(new std::queue<void*>());
context->custom_contexts->push(custom_context);
return custom_context;
}
static void* GetNext(SerializationContext* context) {
void* custom_context = context->custom_contexts->front();
context->custom_contexts->pop();
return custom_context;
}
template <typename MaybeConstUserType>
static void TearDown(MaybeConstUserType& input, void* custom_context) {
Traits::TearDownContext(input, custom_context);
}
};
template <typename Traits>
struct CustomContextHelper<Traits, false> {
template <typename MaybeConstUserType>
static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
return nullptr;
}
static void* GetNext(SerializationContext* context) { return nullptr; }
template <typename MaybeConstUserType>
static void TearDown(MaybeConstUserType& input, void* custom_context) {
DCHECK(!custom_context);
}
};
template <typename ReturnType, typename ParamType, typename InputUserType>
ReturnType CallWithContext(ReturnType (*f)(ParamType, void*),
InputUserType&& input,
void* context) {
return f(std::forward<InputUserType>(input), context);
}
template <typename ReturnType, typename ParamType, typename InputUserType>
ReturnType CallWithContext(ReturnType (*f)(ParamType),
InputUserType&& input,
void* context) {
return f(std::forward<InputUserType>(input));
}
template <typename T, typename MaybeConstUserType>
struct HasGetBeginMethod {
template <typename U>
static char Test(decltype(U::GetBegin(std::declval<MaybeConstUserType&>()))*);
template <typename U>
static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
private:
EnsureTypeIsComplete<T> check_t_;
};
template <
typename Traits,
typename MaybeConstUserType,
typename std::enable_if<
HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>()))
CallGetBeginIfExists(MaybeConstUserType& input) {
return Traits::GetBegin(input);
}
template <
typename Traits,
typename MaybeConstUserType,
typename std::enable_if<
!HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
size_t CallGetBeginIfExists(MaybeConstUserType& input) {
return 0;
}
template <typename T, typename MaybeConstUserType>
struct HasGetDataMethod {
template <typename U>
static char Test(decltype(U::GetData(std::declval<MaybeConstUserType&>()))*);
template <typename U>
static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
private:
EnsureTypeIsComplete<T> check_t_;
};
template <
typename Traits,
typename MaybeConstUserType,
typename std::enable_if<
HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
decltype(Traits::GetData(std::declval<MaybeConstUserType&>()))
CallGetDataIfExists(MaybeConstUserType& input) {
return Traits::GetData(input);
}
template <
typename Traits,
typename MaybeConstUserType,
typename std::enable_if<
!HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr>
void* CallGetDataIfExists(MaybeConstUserType& input) {
return nullptr;
}
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_