blob: 2a7d288d55492322ab451052e727d3fbb18c349c [file] [log] [blame]
// Copyright 2016 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_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_
#include <string.h>
#include "mojo/public/cpp/bindings/array_traits_carray.h"
#include "mojo/public/cpp/bindings/array_traits_stl.h"
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
#include "mojo/public/cpp/bindings/lib/buffer.h"
#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h"
#include "mojo/public/cpp/bindings/lib/map_serialization.h"
#include "mojo/public/cpp/bindings/lib/native_enum_serialization.h"
#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h"
#include "mojo/public/cpp/bindings/lib/string_serialization.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/map_traits_stl.h"
#include "mojo/public/cpp/bindings/string_traits_stl.h"
#include "mojo/public/cpp/bindings/string_traits_string16.h"
#include "mojo/public/cpp/bindings/string_traits_string_piece.h"
namespace mojo {
namespace internal {
template <typename MojomType, typename DataArrayType, typename UserType>
DataArrayType StructSerializeImpl(UserType* input) {
static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value,
"Unexpected type.");
SerializationContext context;
size_t size = PrepareToSerialize<MojomType>(*input, &context);
DCHECK_EQ(size, Align(size));
DataArrayType result(size);
if (size == 0)
return result;
void* result_buffer = &result.front();
// The serialization logic requires that the buffer is 8-byte aligned. If the
// result buffer is not properly aligned, we have to do an extra copy. In
// practice, this should never happen for std::vector.
bool need_copy = !IsAligned(result_buffer);
if (need_copy) {
// calloc sets the memory to all zero.
result_buffer = calloc(size, 1);
DCHECK(IsAligned(result_buffer));
}
Buffer buffer;
buffer.Initialize(result_buffer, size);
typename MojomTypeTraits<MojomType>::Data* data = nullptr;
Serialize<MojomType>(*input, &buffer, &data, &context);
if (need_copy) {
memcpy(&result.front(), result_buffer, size);
free(result_buffer);
}
return result;
}
template <typename MojomType, typename DataArrayType, typename UserType>
bool StructDeserializeImpl(const DataArrayType& input,
UserType* output,
bool (*validate_func)(const void*,
ValidationContext*)) {
static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value,
"Unexpected type.");
using DataType = typename MojomTypeTraits<MojomType>::Data;
// TODO(sammc): Use DataArrayType::empty() once WTF::Vector::empty() exists.
void* input_buffer =
input.size() == 0
? nullptr
: const_cast<void*>(reinterpret_cast<const void*>(&input.front()));
// Please see comments in StructSerializeImpl.
bool need_copy = !IsAligned(input_buffer);
if (need_copy) {
input_buffer = malloc(input.size());
DCHECK(IsAligned(input_buffer));
memcpy(input_buffer, &input.front(), input.size());
}
ValidationContext validation_context(input_buffer, input.size(), 0, 0);
bool result = false;
if (validate_func(input_buffer, &validation_context)) {
auto data = reinterpret_cast<DataType*>(input_buffer);
SerializationContext context;
result = Deserialize<MojomType>(data, output, &context);
}
if (need_copy)
free(input_buffer);
return result;
}
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_