1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ 7 8 #include <string.h> 9 10 #include <type_traits> 11 12 #include "base/numerics/safe_math.h" 13 #include "mojo/public/cpp/bindings/array_traits_span.h" 14 #include "mojo/public/cpp/bindings/array_traits_stl.h" 15 #include "mojo/public/cpp/bindings/lib/array_serialization.h" 16 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 17 #include "mojo/public/cpp/bindings/lib/buffer.h" 18 #include "mojo/public/cpp/bindings/lib/handle_serialization.h" 19 #include "mojo/public/cpp/bindings/lib/map_serialization.h" 20 #include "mojo/public/cpp/bindings/lib/string_serialization.h" 21 #include "mojo/public/cpp/bindings/lib/template_util.h" 22 #include "mojo/public/cpp/bindings/map_traits_flat_map.h" 23 #include "mojo/public/cpp/bindings/map_traits_stl.h" 24 #include "mojo/public/cpp/bindings/message.h" 25 #include "mojo/public/cpp/bindings/string_traits_stl.h" 26 #include "mojo/public/cpp/bindings/string_traits_string_piece.h" 27 28 namespace mojo { 29 namespace internal { 30 31 template <typename MojomType, typename EnableType = void> 32 struct MojomSerializationImplTraits; 33 34 template <typename MojomType> 35 struct MojomSerializationImplTraits< 36 MojomType, 37 typename std::enable_if< 38 BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value>::type> { 39 template <typename MaybeConstUserType, typename WriterType> 40 static void Serialize(MaybeConstUserType& input, 41 Buffer* buffer, 42 WriterType* writer, 43 SerializationContext* context) { 44 mojo::internal::Serialize<MojomType>(input, buffer, writer, context); 45 } 46 }; 47 48 template <typename MojomType> 49 struct MojomSerializationImplTraits< 50 MojomType, 51 typename std::enable_if< 52 BelongsTo<MojomType, MojomTypeCategory::UNION>::value>::type> { 53 template <typename MaybeConstUserType, typename WriterType> 54 static void Serialize(MaybeConstUserType& input, 55 Buffer* buffer, 56 WriterType* writer, 57 SerializationContext* context) { 58 mojo::internal::Serialize<MojomType>(input, buffer, writer, 59 false /* inline */, context); 60 } 61 }; 62 63 template <typename MojomType, typename UserType> 64 mojo::Message SerializeAsMessageImpl(UserType* input) { 65 SerializationContext context; 66 mojo::Message message(0, 0, 0, 0, nullptr); 67 typename MojomTypeTraits<MojomType>::Data::BufferWriter writer; 68 MojomSerializationImplTraits<MojomType>::Serialize( 69 *input, message.payload_buffer(), &writer, &context); 70 message.AttachHandlesFromSerializationContext(&context); 71 return message; 72 } 73 74 template <typename MojomType, typename DataArrayType, typename UserType> 75 DataArrayType SerializeImpl(UserType* input) { 76 static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value || 77 BelongsTo<MojomType, MojomTypeCategory::UNION>::value, 78 "Unexpected type."); 79 Message message = SerializeAsMessageImpl<MojomType>(input); 80 uint32_t size = message.payload_num_bytes(); 81 DataArrayType result(size); 82 if (size) 83 memcpy(&result.front(), message.payload(), size); 84 return result; 85 } 86 87 template <typename MojomType, typename UserType> 88 bool DeserializeImpl(const void* data, 89 size_t data_num_bytes, 90 std::vector<mojo::ScopedHandle> handles, 91 UserType* output, 92 bool (*validate_func)(const void*, ValidationContext*)) { 93 static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value || 94 BelongsTo<MojomType, MojomTypeCategory::UNION>::value, 95 "Unexpected type."); 96 using DataType = typename MojomTypeTraits<MojomType>::Data; 97 98 const void* input_buffer = data_num_bytes == 0 ? nullptr : data; 99 void* aligned_input_buffer = nullptr; 100 101 // Validation code will insist that the input buffer is aligned, so we ensure 102 // that here. If the input data is not aligned, we (sadly) copy into an 103 // aligned buffer. In practice this should happen only rarely if ever. 104 bool need_copy = !IsAligned(input_buffer); 105 if (need_copy) { 106 aligned_input_buffer = malloc(data_num_bytes); 107 DCHECK(IsAligned(aligned_input_buffer)); 108 memcpy(aligned_input_buffer, data, data_num_bytes); 109 input_buffer = aligned_input_buffer; 110 } 111 112 DCHECK(base::IsValueInRangeForNumericType<uint32_t>(data_num_bytes)); 113 ValidationContext validation_context( 114 input_buffer, static_cast<uint32_t>(data_num_bytes), handles.size(), 0); 115 bool result = false; 116 if (validate_func(input_buffer, &validation_context)) { 117 SerializationContext context; 118 *context.mutable_handles() = std::move(handles); 119 result = Deserialize<MojomType>( 120 reinterpret_cast<DataType*>(const_cast<void*>(input_buffer)), output, 121 &context); 122 } 123 124 if (aligned_input_buffer) 125 free(aligned_input_buffer); 126 127 return result; 128 } 129 130 } // namespace internal 131 } // namespace mojo 132 133 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ 134