1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
8 #define __IPC_GLUE_IPCMESSAGEUTILS_H__
12 #include <type_traits>
13 #include "chrome/common/ipc_message.h"
14 #include "chrome/common/ipc_message_utils.h"
15 #include "mozilla/ipc/IPCCore.h"
16 #include "mozilla/MacroForEach.h"
20 // XXX Things that are not necessary if moving implementations to the cpp file
21 #include "base/string_util.h"
24 # pragma warning(disable : 4800)
28 // This condition must be kept in sync with the one in
29 // ipc_message_utils.h, but this dummy definition of
30 // base::FileDescriptor acts as a static assert that we only get one
31 // def or the other (or neither, in which case code using
32 // FileDescriptor fails to build)
34 struct FileDescriptor
{};
39 template <typename
...>
43 template <typename
...>
46 } // namespace mozilla
51 * A helper class for serializing empty structs. Since the struct is empty there
52 * is nothing to write, and a priori we know the result of the read.
55 struct EmptyStructSerializer
{
58 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
60 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
67 struct ParamTraits
<int8_t> {
68 typedef int8_t paramType
;
70 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
71 aWriter
->WriteBytes(&aParam
, sizeof(aParam
));
74 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
75 return aReader
->ReadBytesInto(aResult
, sizeof(*aResult
));
80 struct ParamTraits
<uint8_t> {
81 typedef uint8_t paramType
;
83 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
84 aWriter
->WriteBytes(&aParam
, sizeof(aParam
));
87 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
88 return aReader
->ReadBytesInto(aResult
, sizeof(*aResult
));
93 // See above re: keeping definitions in sync
95 struct ParamTraits
<base::FileDescriptor
> {
96 typedef base::FileDescriptor paramType
;
97 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
98 MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
100 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
101 MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
105 #endif // !defined(XP_UNIX)
108 struct ParamTraits
<mozilla::void_t
> {
109 typedef mozilla::void_t paramType
;
110 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
111 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
112 *aResult
= paramType();
118 struct ParamTraits
<mozilla::null_t
> {
119 typedef mozilla::null_t paramType
;
120 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
121 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
122 *aResult
= paramType();
127 // Helper class for reading bitfields.
128 // If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
129 template <typename ParamType
>
130 struct BitfieldHelper
{
131 // We need this helper because we can't get the address of a bitfield to
132 // pass directly to ReadParam. So instead we read it into a temporary bool
133 // and set the bitfield using a setter function
134 static bool ReadBoolForBitfield(MessageReader
* aReader
, ParamType
* aResult
,
135 void (ParamType::*aSetter
)(bool)) {
137 if (ReadParam(aReader
, &value
)) {
138 (aResult
->*aSetter
)(value
);
145 // A couple of recursive helper functions, allows syntax like:
146 // WriteParams(aMsg, aParam.foo, aParam.bar, aParam.baz)
147 // ReadParams(aMsg, aIter, aParam.foo, aParam.bar, aParam.baz)
149 template <typename
... Ts
>
150 static void WriteParams(MessageWriter
* aWriter
, const Ts
&... aArgs
) {
151 (WriteParam(aWriter
, aArgs
), ...);
154 template <typename
... Ts
>
155 static bool ReadParams(MessageReader
* aReader
, Ts
&... aArgs
) {
156 return (ReadParam(aReader
, &aArgs
) && ...);
159 // Macros that allow syntax like:
160 // DEFINE_IPC_SERIALIZER_WITH_FIELDS(SomeType, member1, member2, member3)
161 // Makes sure that serialize/deserialize code do the same members in the same
163 #define ACCESS_PARAM_FIELD(Field) aParam.Field
165 #define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \
167 struct ParamTraits<Type> { \
168 typedef Type paramType; \
169 static void Write(MessageWriter* aWriter, const paramType& aParam) { \
170 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \
171 (), (__VA_ARGS__))); \
174 static bool Read(MessageReader* aReader, paramType* aResult) { \
175 paramType& aParam = *aResult; \
176 return ReadParams(aReader, \
177 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
182 #define DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(Type) \
184 struct ParamTraits<Type> : public EmptyStructSerializer<Type> {};
186 } /* namespace IPC */
188 #define DEFINE_IPC_SERIALIZER_WITH_SUPER_CLASS_AND_FIELDS(Type, Super, ...) \
190 struct ParamTraits<Type> { \
191 typedef Type paramType; \
192 static void Write(MessageWriter* aWriter, const paramType& aParam) { \
193 WriteParam(aWriter, static_cast<const Super&>(aParam)); \
194 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \
195 (), (__VA_ARGS__))); \
198 static bool Read(MessageReader* aReader, paramType* aResult) { \
199 paramType& aParam = *aResult; \
200 return ReadParam(aReader, static_cast<Super*>(aResult)) && \
201 ReadParams(aReader, \
202 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
207 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */