Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / ipc / glue / IPCMessageUtils.h
blobcdcd3c574a60fb132038b8411e53ff7717133e68
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__
10 #include <cstdint>
11 #include <string>
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"
18 class PickleIterator;
20 // XXX Things that are not necessary if moving implementations to the cpp file
21 #include "base/string_util.h"
23 #ifdef _MSC_VER
24 # pragma warning(disable : 4800)
25 #endif
27 #if !defined(XP_UNIX)
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)
33 namespace base {
34 struct FileDescriptor {};
35 } // namespace base
36 #endif
38 namespace mozilla {
39 template <typename...>
40 class Variant;
42 namespace detail {
43 template <typename...>
44 struct VariantTag;
46 } // namespace mozilla
48 namespace IPC {
50 /**
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
61 * in such cases.
63 template <typename T>
64 struct PlainOldDataSerializer {
65 static_assert(
66 std::is_trivially_copyable<T>::value,
67 "PlainOldDataSerializer can only be used with trivially copyable types!");
69 typedef T paramType;
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));
80 /**
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.
84 template <typename T>
85 struct EmptyStructSerializer {
86 typedef T paramType;
88 static void Write(MessageWriter* aWriter, const paramType& aParam) {}
90 static bool Read(MessageReader* aReader, paramType* aResult) {
91 *aResult = {};
92 return true;
96 template <>
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));
109 template <>
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
124 template <>
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");
132 return false;
135 #endif // !defined(XP_UNIX)
137 template <>
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();
143 return true;
147 template <>
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();
153 return true;
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)) {
166 bool value;
167 if (ReadParam(aReader, &value)) {
168 (aResult->*aSetter)(value);
169 return true;
171 return false;
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
192 // order.
193 #define ACCESS_PARAM_FIELD(Field) aParam.Field
195 #define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \
196 template <> \
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, (, ), (), \
208 (__VA_ARGS__))); \
212 #define DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(Type) \
213 template <> \
214 struct ParamTraits<Type> : public EmptyStructSerializer<Type> {};
216 } /* namespace IPC */
218 #define DEFINE_IPC_SERIALIZER_WITH_SUPER_CLASS_AND_FIELDS(Type, Super, ...) \
219 template <> \
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, (, ), (), \
233 (__VA_ARGS__))); \
237 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */