#pragma once
#include "ArgumentCoder.h"
#include "Attachment.h"
#include "MessageNames.h"
#include "StringReference.h"
#include <WebCore/ContextMenuItem.h>
#include <WebCore/SharedBuffer.h>
#include <wtf/OptionSet.h>
#include <wtf/Vector.h>
namespace IPC {
enum class MessageFlags : uint8_t;
enum class MessageName : uint16_t;
enum class ShouldDispatchWhenWaitingForSyncReply : uint8_t;
class Encoder final {
WTF_MAKE_FAST_ALLOCATED;
public:
Encoder(MessageName, uint64_t destinationID);
~Encoder();
ReceiverName messageReceiverName() const { return receiverName(m_messageName); }
MessageName messageName() const { return m_messageName; }
uint64_t destinationID() const { return m_destinationID; }
bool isSyncMessage() const { return messageIsSync(messageName()); }
void setShouldDispatchMessageWhenWaitingForSyncReply(ShouldDispatchWhenWaitingForSyncReply);
ShouldDispatchWhenWaitingForSyncReply shouldDispatchMessageWhenWaitingForSyncReply() const;
void setFullySynchronousModeForTesting();
void setShouldMaintainOrderingWithAsyncMessages();
void wrapForTesting(std::unique_ptr<Encoder>);
void encodeFixedLengthData(const uint8_t* data, size_t, size_t alignment);
template<typename T, std::enable_if_t<!std::is_enum<typename std::remove_const_t<std::remove_reference_t<T>>>::value && !std::is_arithmetic<typename std::remove_const_t<std::remove_reference_t<T>>>::value>* = nullptr>
void encode(T&& t)
{
ArgumentCoder<typename std::remove_const<typename std::remove_reference<T>::type>::type>::encode(*this, std::forward<T>(t));
}
template<typename E, std::enable_if_t<std::is_enum<E>::value>* = nullptr>
Encoder& operator<<(E&& enumValue)
{
ASSERT(WTF::isValidEnum<E>(WTF::enumToUnderlyingType<E>(enumValue)));
encode(WTF::enumToUnderlyingType<E>(enumValue));
return *this;
}
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
Encoder& operator<<(T&& t)
{
encode(std::forward<T>(t));
return *this;
}
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value>* = nullptr>
void encode(T value)
{
encodeFixedLengthData(reinterpret_cast<const uint8_t*>(&value), sizeof(T), alignof(T));
}
uint8_t* buffer() const { return m_buffer; }
size_t bufferSize() const { return m_bufferSize; }
void addAttachment(Attachment&&);
Vector<Attachment> releaseAttachments();
void reserve(size_t);
static const bool isIPCEncoder = true;
template<typename T>
static RefPtr<WebCore::SharedBuffer> encodeSingleObject(const T& object)
{
Encoder encoder(ConstructWithoutHeader);
encoder << object;
if (encoder.hasAttachments()) {
ASSERT_NOT_REACHED();
return nullptr;
}
return WebCore::SharedBuffer::create(encoder.buffer(), encoder.bufferSize());
}
private:
enum ConstructWithoutHeaderTag { ConstructWithoutHeader };
Encoder(ConstructWithoutHeaderTag);
uint8_t* grow(size_t alignment, size_t);
template<typename E, std::enable_if_t<std::is_enum<E>::value>* = nullptr>
void encode(E enumValue)
{
ASSERT(WTF::isValidEnum<E>(WTF::enumToUnderlyingType<E>(enumValue)));
encode(WTF::enumToUnderlyingType<E>(enumValue));
}
bool hasAttachments() const;
void encodeHeader();
const OptionSet<MessageFlags>& messageFlags() const;
OptionSet<MessageFlags>& messageFlags();
MessageName m_messageName;
uint64_t m_destinationID;
uint8_t m_inlineBuffer[512];
uint8_t* m_buffer;
uint8_t* m_bufferPointer;
size_t m_bufferSize;
size_t m_bufferCapacity;
Vector<Attachment> m_attachments;
};
}