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 plain-old data (POD) structures.
52 * The memory representation of the structure is written to and read from
53 * the serialized stream directly, without individual processing of the
54 * structure's members.
56 * Derive ParamTraits<T> from PlainOldDataSerializer<T> if T is POD.
58 * Note: For POD structures with enumeration fields, this will not do
59 * validation of the enum values the way serializing the fields
60 * individually would. Prefer serializing the fields individually
64 struct PlainOldDataSerializer
{
66 std::is_trivially_copyable
<T
>::value
,
67 "PlainOldDataSerializer can only be used with trivially copyable types!");
71 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
72 aWriter
->WriteBytes(&aParam
, sizeof(aParam
));
75 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
76 return aReader
->ReadBytesInto(aResult
, sizeof(paramType
));
81 * A helper class for serializing empty structs. Since the struct is empty there
82 * is nothing to write, and a priori we know the result of the read.
85 struct EmptyStructSerializer
{
88 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
90 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
97 struct ParamTraits
<int8_t> {
98 typedef int8_t paramType
;
100 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
101 aWriter
->WriteBytes(&aParam
, sizeof(aParam
));
104 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
105 return aReader
->ReadBytesInto(aResult
, sizeof(*aResult
));
110 struct ParamTraits
<uint8_t> {
111 typedef uint8_t paramType
;
113 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
114 aWriter
->WriteBytes(&aParam
, sizeof(aParam
));
117 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
118 return aReader
->ReadBytesInto(aResult
, sizeof(*aResult
));
122 #if !defined(XP_UNIX)
123 // See above re: keeping definitions in sync
125 struct ParamTraits
<base::FileDescriptor
> {
126 typedef base::FileDescriptor paramType
;
127 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
128 MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
130 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
131 MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
135 #endif // !defined(XP_UNIX)
138 struct ParamTraits
<mozilla::void_t
> {
139 typedef mozilla::void_t paramType
;
140 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
141 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
142 *aResult
= paramType();
148 struct ParamTraits
<mozilla::null_t
> {
149 typedef mozilla::null_t paramType
;
150 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {}
151 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
152 *aResult
= paramType();
157 // Helper class for reading bitfields.
158 // If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
159 template <typename ParamType
>
160 struct BitfieldHelper
{
161 // We need this helper because we can't get the address of a bitfield to
162 // pass directly to ReadParam. So instead we read it into a temporary bool
163 // and set the bitfield using a setter function
164 static bool ReadBoolForBitfield(MessageReader
* aReader
, ParamType
* aResult
,
165 void (ParamType::*aSetter
)(bool)) {
167 if (ReadParam(aReader
, &value
)) {
168 (aResult
->*aSetter
)(value
);
175 // A couple of recursive helper functions, allows syntax like:
176 // WriteParams(aMsg, aParam.foo, aParam.bar, aParam.baz)
177 // ReadParams(aMsg, aIter, aParam.foo, aParam.bar, aParam.baz)
179 template <typename
... Ts
>
180 static void WriteParams(MessageWriter
* aWriter
, const Ts
&... aArgs
) {
181 (WriteParam(aWriter
, aArgs
), ...);
184 template <typename
... Ts
>
185 static bool ReadParams(MessageReader
* aReader
, Ts
&... aArgs
) {
186 return (ReadParam(aReader
, &aArgs
) && ...);
189 // Macros that allow syntax like:
190 // DEFINE_IPC_SERIALIZER_WITH_FIELDS(SomeType, member1, member2, member3)
191 // Makes sure that serialize/deserialize code do the same members in the same
193 #define ACCESS_PARAM_FIELD(Field) aParam.Field
195 #define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \
197 struct ParamTraits<Type> { \
198 typedef Type paramType; \
199 static void Write(MessageWriter* aWriter, const paramType& aParam) { \
200 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \
201 (), (__VA_ARGS__))); \
204 static bool Read(MessageReader* aReader, paramType* aResult) { \
205 paramType& aParam = *aResult; \
206 return ReadParams(aReader, \
207 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
212 #define DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(Type) \
214 struct ParamTraits<Type> : public EmptyStructSerializer<Type> {};
216 } /* namespace IPC */
218 #define DEFINE_IPC_SERIALIZER_WITH_SUPER_CLASS_AND_FIELDS(Type, Super, ...) \
220 struct ParamTraits<Type> { \
221 typedef Type paramType; \
222 static void Write(MessageWriter* aWriter, const paramType& aParam) { \
223 WriteParam(aWriter, static_cast<const Super&>(aParam)); \
224 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \
225 (), (__VA_ARGS__))); \
228 static bool Read(MessageReader* aReader, paramType* aResult) { \
229 paramType& aParam = *aResult; \
230 return ReadParam(aReader, static_cast<Super*>(aResult)) && \
231 ReadParams(aReader, \
232 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
237 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */