1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2015 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stddef.h> 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <limits> 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/logging.h" 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/pickle.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "ipc/ipc_param_traits.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/array_internal.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/bindings_internal.h" 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/native_struct_data.h" 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/serialization_forward.h" 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/serialization_util.h" 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/native_struct.h" 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace internal { 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztemplate <typename MaybeConstUserType> 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct NativeStructSerializerImpl { 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez using UserType = typename std::remove_const<MaybeConstUserType>::type; 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez using Traits = IPC::ParamTraits<UserType>; 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static size_t PrepareToSerialize(MaybeConstUserType& value, 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context) { 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::PickleSizer sizer; 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traits::GetSize(&sizer, value); 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return Align(sizer.payload_size() + sizeof(ArrayHeader)); 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static void Serialize(MaybeConstUserType& value, 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Buffer* buffer, 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez NativeStruct_Data** out, 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context) { 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Pickle pickle; 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traits::Write(&pickle, value); 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if DCHECK_IS_ON() 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::PickleSizer sizer; 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Traits::GetSize(&sizer, value); 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(sizer.payload_size(), pickle.payload_size()); 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t total_size = pickle.payload_size() + sizeof(ArrayHeader); 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LT(total_size, std::numeric_limits<uint32_t>::max()); 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Allocate a uint8 array, initialize its header, and copy the Pickle in. 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ArrayHeader* header = 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reinterpret_cast<ArrayHeader*>(buffer->Allocate(total_size)); 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header->num_bytes = static_cast<uint32_t>(total_size); 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header->num_elements = static_cast<uint32_t>(pickle.payload_size()); 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memcpy(reinterpret_cast<char*>(header) + sizeof(ArrayHeader), 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pickle.payload(), pickle.payload_size()); 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *out = reinterpret_cast<NativeStruct_Data*>(header); 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static bool Deserialize(NativeStruct_Data* data, 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserType* out, 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context) { 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!data) 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Construct a temporary base::Pickle view over the array data. Note that 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the Array_Data is laid out like this: 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // and base::Pickle expects to view data like this: 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // [payload_size (4 bytes)] [header bytes ...] [payload...] 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Because ArrayHeader's num_bytes includes the length of the header and 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Pickle's payload_size does not, we need to adjust the stored value 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // momentarily so Pickle can view the data. 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data); 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header->num_bytes -= sizeof(ArrayHeader); 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Construct a view over the full Array_Data, including our hacked up 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // header. Pickle will infer from this that the header is 8 bytes long, 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // and the payload will contain all of the pickled bytes. 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Pickle pickle_view(reinterpret_cast<const char*>(header), 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header->num_bytes + sizeof(ArrayHeader)); 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::PickleIterator iter(pickle_view); 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!Traits::Read(&pickle_view, &iter, out)) 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Return the header to its original state. 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header->num_bytes += sizeof(ArrayHeader); 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct UnmappedNativeStructSerializerImpl { 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static size_t PrepareToSerialize(const NativeStructPtr& input, 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context); 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static void Serialize(const NativeStructPtr& input, 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Buffer* buffer, 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez NativeStruct_Data** output, 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context); 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static bool Deserialize(NativeStruct_Data* input, 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez NativeStructPtr* output, 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SerializationContext* context); 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztemplate <> 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct NativeStructSerializerImpl<NativeStructPtr> 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : public UnmappedNativeStructSerializerImpl {}; 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztemplate <> 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct NativeStructSerializerImpl<const NativeStructPtr> 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : public UnmappedNativeStructSerializerImpl {}; 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztemplate <typename MaybeConstUserType> 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct Serializer<NativeStructPtr, MaybeConstUserType> 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : public NativeStructSerializerImpl<MaybeConstUserType> {}; 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace internal 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 133