You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
5.1 KiB
134 lines
5.1 KiB
4 months ago
|
// 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 <type_traits>
|
||
|
|
||
|
#include "base/numerics/safe_math.h"
|
||
|
#include "mojo/public/cpp/bindings/array_traits_span.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/bindings_internal.h"
|
||
|
#include "mojo/public/cpp/bindings/lib/buffer.h"
|
||
|
#include "mojo/public/cpp/bindings/lib/handle_serialization.h"
|
||
|
#include "mojo/public/cpp/bindings/lib/map_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_flat_map.h"
|
||
|
#include "mojo/public/cpp/bindings/map_traits_stl.h"
|
||
|
#include "mojo/public/cpp/bindings/message.h"
|
||
|
#include "mojo/public/cpp/bindings/string_traits_stl.h"
|
||
|
#include "mojo/public/cpp/bindings/string_traits_string_piece.h"
|
||
|
|
||
|
namespace mojo {
|
||
|
namespace internal {
|
||
|
|
||
|
template <typename MojomType, typename EnableType = void>
|
||
|
struct MojomSerializationImplTraits;
|
||
|
|
||
|
template <typename MojomType>
|
||
|
struct MojomSerializationImplTraits<
|
||
|
MojomType,
|
||
|
typename std::enable_if<
|
||
|
BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value>::type> {
|
||
|
template <typename MaybeConstUserType, typename WriterType>
|
||
|
static void Serialize(MaybeConstUserType& input,
|
||
|
Buffer* buffer,
|
||
|
WriterType* writer,
|
||
|
SerializationContext* context) {
|
||
|
mojo::internal::Serialize<MojomType>(input, buffer, writer, context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename MojomType>
|
||
|
struct MojomSerializationImplTraits<
|
||
|
MojomType,
|
||
|
typename std::enable_if<
|
||
|
BelongsTo<MojomType, MojomTypeCategory::UNION>::value>::type> {
|
||
|
template <typename MaybeConstUserType, typename WriterType>
|
||
|
static void Serialize(MaybeConstUserType& input,
|
||
|
Buffer* buffer,
|
||
|
WriterType* writer,
|
||
|
SerializationContext* context) {
|
||
|
mojo::internal::Serialize<MojomType>(input, buffer, writer,
|
||
|
false /* inline */, context);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename MojomType, typename UserType>
|
||
|
mojo::Message SerializeAsMessageImpl(UserType* input) {
|
||
|
SerializationContext context;
|
||
|
mojo::Message message(0, 0, 0, 0, nullptr);
|
||
|
typename MojomTypeTraits<MojomType>::Data::BufferWriter writer;
|
||
|
MojomSerializationImplTraits<MojomType>::Serialize(
|
||
|
*input, message.payload_buffer(), &writer, &context);
|
||
|
message.AttachHandlesFromSerializationContext(&context);
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
template <typename MojomType, typename DataArrayType, typename UserType>
|
||
|
DataArrayType SerializeImpl(UserType* input) {
|
||
|
static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value ||
|
||
|
BelongsTo<MojomType, MojomTypeCategory::UNION>::value,
|
||
|
"Unexpected type.");
|
||
|
Message message = SerializeAsMessageImpl<MojomType>(input);
|
||
|
uint32_t size = message.payload_num_bytes();
|
||
|
DataArrayType result(size);
|
||
|
if (size)
|
||
|
memcpy(&result.front(), message.payload(), size);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
template <typename MojomType, typename UserType>
|
||
|
bool DeserializeImpl(const void* data,
|
||
|
size_t data_num_bytes,
|
||
|
std::vector<mojo::ScopedHandle> handles,
|
||
|
UserType* output,
|
||
|
bool (*validate_func)(const void*, ValidationContext*)) {
|
||
|
static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value ||
|
||
|
BelongsTo<MojomType, MojomTypeCategory::UNION>::value,
|
||
|
"Unexpected type.");
|
||
|
using DataType = typename MojomTypeTraits<MojomType>::Data;
|
||
|
|
||
|
const void* input_buffer = data_num_bytes == 0 ? nullptr : data;
|
||
|
void* aligned_input_buffer = nullptr;
|
||
|
|
||
|
// Validation code will insist that the input buffer is aligned, so we ensure
|
||
|
// that here. If the input data is not aligned, we (sadly) copy into an
|
||
|
// aligned buffer. In practice this should happen only rarely if ever.
|
||
|
bool need_copy = !IsAligned(input_buffer);
|
||
|
if (need_copy) {
|
||
|
aligned_input_buffer = malloc(data_num_bytes);
|
||
|
DCHECK(IsAligned(aligned_input_buffer));
|
||
|
memcpy(aligned_input_buffer, data, data_num_bytes);
|
||
|
input_buffer = aligned_input_buffer;
|
||
|
}
|
||
|
|
||
|
DCHECK(base::IsValueInRangeForNumericType<uint32_t>(data_num_bytes));
|
||
|
ValidationContext validation_context(
|
||
|
input_buffer, static_cast<uint32_t>(data_num_bytes), handles.size(), 0);
|
||
|
bool result = false;
|
||
|
if (validate_func(input_buffer, &validation_context)) {
|
||
|
SerializationContext context;
|
||
|
*context.mutable_handles() = std::move(handles);
|
||
|
result = Deserialize<MojomType>(
|
||
|
reinterpret_cast<DataType*>(const_cast<void*>(input_buffer)), output,
|
||
|
&context);
|
||
|
}
|
||
|
|
||
|
if (aligned_input_buffer)
|
||
|
free(aligned_input_buffer);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
} // namespace internal
|
||
|
} // namespace mojo
|
||
|
|
||
|
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_
|