| // Copyright 2015 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_NATIVE_STRUCT_SERIALIZATION_H_ |
| #define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <limits> |
| |
| #include "base/logging.h" |
| #include "base/pickle.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_param_traits.h" |
| #include "mojo/public/cpp/bindings/bindings_export.h" |
| #include "mojo/public/cpp/bindings/lib/array_internal.h" |
| #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
| #include "mojo/public/cpp/bindings/lib/serialization_forward.h" |
| #include "mojo/public/cpp/bindings/lib/serialization_util.h" |
| #include "mojo/public/interfaces/bindings/native_struct.mojom.h" |
| |
| namespace mojo { |
| namespace internal { |
| |
| // Base class for the templated native struct serialization interface below, |
| // used to consolidated some shared logic and provide a basic |
| // Serialize/Deserialize for [Native] mojom structs which do not have a |
| // registered typemap in the current configuration (i.e. structs that are |
| // represented by a raw native::NativeStruct mojom struct in C++ bindings.) |
| struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { |
| static void Serialize( |
| const native::NativeStructPtr& input, |
| Buffer* buffer, |
| native::internal::NativeStruct_Data::BufferWriter* writer, |
| SerializationContext* context); |
| |
| static bool Deserialize(native::internal::NativeStruct_Data* input, |
| native::NativeStructPtr* output, |
| SerializationContext* context); |
| |
| static void SerializeMessageContents( |
| IPC::Message* message, |
| Buffer* buffer, |
| native::internal::NativeStruct_Data::BufferWriter* writer, |
| SerializationContext* context); |
| |
| static bool DeserializeMessageAttachments( |
| native::internal::NativeStruct_Data* data, |
| SerializationContext* context, |
| IPC::Message* message); |
| }; |
| |
| template <typename MaybeConstUserType> |
| struct NativeStructSerializerImpl { |
| using UserType = typename std::remove_const<MaybeConstUserType>::type; |
| using Traits = IPC::ParamTraits<UserType>; |
| |
| static void Serialize( |
| MaybeConstUserType& value, |
| Buffer* buffer, |
| native::internal::NativeStruct_Data::BufferWriter* writer, |
| SerializationContext* context) { |
| IPC::Message message; |
| Traits::Write(&message, value); |
| UnmappedNativeStructSerializerImpl::SerializeMessageContents( |
| &message, buffer, writer, context); |
| } |
| |
| static bool Deserialize(native::internal::NativeStruct_Data* data, |
| UserType* out, |
| SerializationContext* context) { |
| if (!data) |
| return false; |
| |
| // Construct a temporary base::Pickle view over the array data. Note that |
| // the Array_Data is laid out like this: |
| // |
| // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] |
| // |
| // and base::Pickle expects to view data like this: |
| // |
| // [payload_size (4 bytes)] [header bytes ...] [payload...] |
| // |
| // Because ArrayHeader's num_bytes includes the length of the header and |
| // Pickle's payload_size does not, we need to adjust the stored value |
| // momentarily so Pickle can view the data. |
| ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data->data.Get()); |
| DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); |
| header->num_bytes -= sizeof(ArrayHeader); |
| |
| { |
| // Construct a view over the full Array_Data, including our hacked up |
| // header. Pickle will infer from this that the header is 8 bytes long, |
| // and the payload will contain all of the pickled bytes. |
| IPC::Message message_view(reinterpret_cast<const char*>(header), |
| header->num_bytes + sizeof(ArrayHeader)); |
| base::PickleIterator iter(message_view); |
| if (!UnmappedNativeStructSerializerImpl::DeserializeMessageAttachments( |
| data, context, &message_view)) { |
| return false; |
| } |
| |
| if (!Traits::Read(&message_view, &iter, out)) |
| return false; |
| } |
| |
| // Return the header to its original state. |
| header->num_bytes += sizeof(ArrayHeader); |
| |
| return true; |
| } |
| }; |
| |
| template <> |
| struct NativeStructSerializerImpl<native::NativeStructPtr> |
| : public UnmappedNativeStructSerializerImpl {}; |
| |
| template <> |
| struct NativeStructSerializerImpl<const native::NativeStructPtr> |
| : public UnmappedNativeStructSerializerImpl {}; |
| |
| template <typename MaybeConstUserType> |
| struct Serializer<native::NativeStructDataView, MaybeConstUserType> |
| : public NativeStructSerializerImpl<MaybeConstUserType> {}; |
| |
| } // namespace internal |
| } // namespace mojo |
| |
| #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ |