// 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_