• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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