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_NATIVE_ENUM_SERIALIZATION_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <type_traits>
12
13#include "base/logging.h"
14#include "base/pickle.h"
15#include "ipc/ipc_param_traits.h"
16#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
17#include "mojo/public/cpp/bindings/native_enum.h"
18
19namespace mojo {
20namespace internal {
21
22template <typename MaybeConstUserType>
23struct NativeEnumSerializerImpl {
24  using UserType = typename std::remove_const<MaybeConstUserType>::type;
25  using Traits = IPC::ParamTraits<UserType>;
26
27  // IPC_ENUM_TRAITS* macros serialize enum as int, make sure that fits into
28  // mojo native-only enum.
29  static_assert(sizeof(NativeEnum) >= sizeof(int),
30                "Cannot store the serialization result in NativeEnum.");
31
32  static void Serialize(UserType input, int32_t* output) {
33    base::Pickle pickle;
34    Traits::Write(&pickle, input);
35
36    CHECK_GE(sizeof(int32_t), pickle.payload_size());
37    *output = 0;
38    memcpy(reinterpret_cast<char*>(output), pickle.payload(),
39           pickle.payload_size());
40  }
41
42  struct PickleData {
43    uint32_t payload_size;
44    int32_t value;
45  };
46  static_assert(sizeof(PickleData) == 8, "PickleData size mismatch.");
47
48  static bool Deserialize(int32_t input, UserType* output) {
49    PickleData data = {sizeof(int32_t), input};
50    base::Pickle pickle_view(reinterpret_cast<const char*>(&data),
51                             sizeof(PickleData));
52    base::PickleIterator iter(pickle_view);
53    return Traits::Read(&pickle_view, &iter, output);
54  }
55};
56
57struct UnmappedNativeEnumSerializerImpl {
58  static void Serialize(NativeEnum input, int32_t* output) {
59    *output = static_cast<int32_t>(input);
60  }
61  static bool Deserialize(int32_t input, NativeEnum* output) {
62    *output = static_cast<NativeEnum>(input);
63    return true;
64  }
65};
66
67template <>
68struct NativeEnumSerializerImpl<NativeEnum>
69    : public UnmappedNativeEnumSerializerImpl {};
70
71template <>
72struct NativeEnumSerializerImpl<const NativeEnum>
73    : public UnmappedNativeEnumSerializerImpl {};
74
75template <typename MaybeConstUserType>
76struct Serializer<NativeEnum, MaybeConstUserType>
77    : public NativeEnumSerializerImpl<MaybeConstUserType> {};
78
79}  // namespace internal
80}  // namespace mojo
81
82#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_
83