aboutsummaryrefslogtreecommitdiff
path: root/mojo/public/cpp/bindings/lib/serialization.h
blob: 2a7d288d55492322ab451052e727d3fbb18c349c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright 2016 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_SERIALIZATION_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_

#include <string.h>

#include "mojo/public/cpp/bindings/array_traits_carray.h"
#include "mojo/public/cpp/bindings/array_traits_stl.h"
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
#include "mojo/public/cpp/bindings/lib/buffer.h"
#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h"
#include "mojo/public/cpp/bindings/lib/map_serialization.h"
#include "mojo/public/cpp/bindings/lib/native_enum_serialization.h"
#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h"
#include "mojo/public/cpp/bindings/lib/string_serialization.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/map_traits_stl.h"
#include "mojo/public/cpp/bindings/string_traits_stl.h"
#include "mojo/public/cpp/bindings/string_traits_string16.h"
#include "mojo/public/cpp/bindings/string_traits_string_piece.h"

namespace mojo {
namespace internal {

template <typename MojomType, typename DataArrayType, typename UserType>
DataArrayType StructSerializeImpl(UserType* input) {
  static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value,
                "Unexpected type.");

  SerializationContext context;
  size_t size = PrepareToSerialize<MojomType>(*input, &context);
  DCHECK_EQ(size, Align(size));

  DataArrayType result(size);
  if (size == 0)
    return result;

  void* result_buffer = &result.front();
  // The serialization logic requires that the buffer is 8-byte aligned. If the
  // result buffer is not properly aligned, we have to do an extra copy. In
  // practice, this should never happen for std::vector.
  bool need_copy = !IsAligned(result_buffer);

  if (need_copy) {
    // calloc sets the memory to all zero.
    result_buffer = calloc(size, 1);
    DCHECK(IsAligned(result_buffer));
  }

  Buffer buffer;
  buffer.Initialize(result_buffer, size);
  typename MojomTypeTraits<MojomType>::Data* data = nullptr;
  Serialize<MojomType>(*input, &buffer, &data, &context);

  if (need_copy) {
    memcpy(&result.front(), result_buffer, size);
    free(result_buffer);
  }

  return result;
}

template <typename MojomType, typename DataArrayType, typename UserType>
bool StructDeserializeImpl(const DataArrayType& input,
                           UserType* output,
                           bool (*validate_func)(const void*,
                                                 ValidationContext*)) {
  static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value,
                "Unexpected type.");
  using DataType = typename MojomTypeTraits<MojomType>::Data;

  // TODO(sammc): Use DataArrayType::empty() once WTF::Vector::empty() exists.
  void* input_buffer =
      input.size() == 0
          ? nullptr
          : const_cast<void*>(reinterpret_cast<const void*>(&input.front()));

  // Please see comments in StructSerializeImpl.
  bool need_copy = !IsAligned(input_buffer);

  if (need_copy) {
    input_buffer = malloc(input.size());
    DCHECK(IsAligned(input_buffer));
    memcpy(input_buffer, &input.front(), input.size());
  }

  ValidationContext validation_context(input_buffer, input.size(), 0, 0);
  bool result = false;
  if (validate_func(input_buffer, &validation_context)) {
    auto data = reinterpret_cast<DataType*>(input_buffer);
    SerializationContext context;
    result = Deserialize<MojomType>(data, output, &context);
  }

  if (need_copy)
    free(input_buffer);

  return result;
}

}  // namespace internal
}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_