|
@@ -11,6 +11,7 @@
|
|
|
#include <AK/StdLibExtras.h>
|
|
|
#include <AK/Variant.h>
|
|
|
#include <LibCore/SharedCircularQueue.h>
|
|
|
+#include <LibIPC/Concepts.h>
|
|
|
#include <LibIPC/Forward.h>
|
|
|
#include <LibIPC/Message.h>
|
|
|
|
|
@@ -30,100 +31,37 @@ public:
|
|
|
{
|
|
|
}
|
|
|
|
|
|
- Encoder& operator<<(bool);
|
|
|
- Encoder& operator<<(u8);
|
|
|
- Encoder& operator<<(u16);
|
|
|
- Encoder& operator<<(unsigned);
|
|
|
- Encoder& operator<<(unsigned long);
|
|
|
- Encoder& operator<<(unsigned long long);
|
|
|
- Encoder& operator<<(i8);
|
|
|
- Encoder& operator<<(i16);
|
|
|
- Encoder& operator<<(i32);
|
|
|
- Encoder& operator<<(i64);
|
|
|
- Encoder& operator<<(float);
|
|
|
- Encoder& operator<<(double);
|
|
|
- Encoder& operator<<(char const*);
|
|
|
- Encoder& operator<<(StringView);
|
|
|
- Encoder& operator<<(DeprecatedString const&);
|
|
|
- Encoder& operator<<(ByteBuffer const&);
|
|
|
- Encoder& operator<<(JsonValue const&);
|
|
|
- Encoder& operator<<(URL const&);
|
|
|
- Encoder& operator<<(Dictionary const&);
|
|
|
- Encoder& operator<<(File const&);
|
|
|
- Encoder& operator<<(AK::Empty const&);
|
|
|
- template<typename K, typename V>
|
|
|
- Encoder& operator<<(HashMap<K, V> const& hashmap)
|
|
|
- {
|
|
|
- *this << (u32)hashmap.size();
|
|
|
- for (auto it : hashmap) {
|
|
|
- *this << it.key;
|
|
|
- *this << it.value;
|
|
|
- }
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- template<typename K, typename V>
|
|
|
- Encoder& operator<<(OrderedHashMap<K, V> const& hashmap)
|
|
|
+ template<typename T>
|
|
|
+ Encoder& operator<<(T const& value)
|
|
|
{
|
|
|
- *this << (u32)hashmap.size();
|
|
|
- for (auto it : hashmap) {
|
|
|
- *this << it.key;
|
|
|
- *this << it.value;
|
|
|
- }
|
|
|
+ encode(value);
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
|
- Encoder& operator<<(Vector<T> const& vector)
|
|
|
- {
|
|
|
- *this << (u64)vector.size();
|
|
|
- for (auto& value : vector)
|
|
|
- *this << value;
|
|
|
- return *this;
|
|
|
- }
|
|
|
+ bool encode(T const& value);
|
|
|
|
|
|
- template<typename T, size_t Size>
|
|
|
- Encoder& operator<<(Core::SharedSingleProducerCircularQueue<T, Size> const& queue)
|
|
|
+ ErrorOr<void> extend_capacity(size_t capacity)
|
|
|
{
|
|
|
- *this << IPC::File(queue.fd());
|
|
|
- return *this;
|
|
|
+ return m_buffer.data.try_ensure_capacity(m_buffer.data.size() + capacity);
|
|
|
}
|
|
|
|
|
|
- template<typename... VariantTypes>
|
|
|
- Encoder& operator<<(AK::Variant<VariantTypes...> const& variant)
|
|
|
+ void append(u8 value)
|
|
|
{
|
|
|
- *this << variant.index();
|
|
|
- variant.visit([this](auto const& underlying_value) { *this << underlying_value; });
|
|
|
- return *this;
|
|
|
+ m_buffer.data.unchecked_append(value);
|
|
|
}
|
|
|
|
|
|
- template<Enum T>
|
|
|
- Encoder& operator<<(T const& enum_value)
|
|
|
+ ErrorOr<void> append(u8 const* values, size_t count)
|
|
|
{
|
|
|
- *this << AK::to_underlying(enum_value);
|
|
|
- return *this;
|
|
|
+ TRY(extend_capacity(count));
|
|
|
+ m_buffer.data.unchecked_append(values, count);
|
|
|
+ return {};
|
|
|
}
|
|
|
|
|
|
- template<typename T>
|
|
|
- Encoder& operator<<(T const& value)
|
|
|
+ ErrorOr<void> append_file_descriptor(int fd)
|
|
|
{
|
|
|
- encode(value);
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- template<typename T>
|
|
|
- Encoder& operator<<(Optional<T> const& optional)
|
|
|
- {
|
|
|
- *this << optional.has_value();
|
|
|
- if (optional.has_value())
|
|
|
- *this << optional.value();
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- template<typename T>
|
|
|
- void encode(T const& value)
|
|
|
- {
|
|
|
- IPC::encode(*this, value);
|
|
|
+ auto auto_fd = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AutoCloseFileDescriptor(fd)));
|
|
|
+ return m_buffer.fds.try_append(move(auto_fd));
|
|
|
}
|
|
|
|
|
|
private:
|
|
@@ -133,4 +71,137 @@ private:
|
|
|
MessageBuffer& m_buffer;
|
|
|
};
|
|
|
|
|
|
+template<Arithmetic T>
|
|
|
+bool encode(Encoder& encoder, T const& value)
|
|
|
+{
|
|
|
+ if (encoder.extend_capacity(sizeof(T)).is_error())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if constexpr (sizeof(T) == 1) {
|
|
|
+ encoder.append(static_cast<u8>(value));
|
|
|
+ } else if constexpr (sizeof(T) == 2) {
|
|
|
+ encoder.append(static_cast<u8>(value));
|
|
|
+ encoder.append(static_cast<u8>(value >> 8));
|
|
|
+ } else if constexpr (sizeof(T) == 4) {
|
|
|
+ encoder.append(static_cast<u8>(value));
|
|
|
+ encoder.append(static_cast<u8>(value >> 8));
|
|
|
+ encoder.append(static_cast<u8>(value >> 16));
|
|
|
+ encoder.append(static_cast<u8>(value >> 24));
|
|
|
+ } else if constexpr (sizeof(T) == 8) {
|
|
|
+ encoder.append(static_cast<u8>(value));
|
|
|
+ encoder.append(static_cast<u8>(value >> 8));
|
|
|
+ encoder.append(static_cast<u8>(value >> 16));
|
|
|
+ encoder.append(static_cast<u8>(value >> 24));
|
|
|
+ encoder.append(static_cast<u8>(value >> 32));
|
|
|
+ encoder.append(static_cast<u8>(value >> 40));
|
|
|
+ encoder.append(static_cast<u8>(value >> 48));
|
|
|
+ encoder.append(static_cast<u8>(value >> 56));
|
|
|
+ } else {
|
|
|
+ static_assert(DependentFalse<T>);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template<Enum T>
|
|
|
+bool encode(Encoder& encoder, T const& value)
|
|
|
+{
|
|
|
+ return encoder.encode(to_underlying(value));
|
|
|
+}
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, float const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, double const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, StringView const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, DeprecatedString const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, ByteBuffer const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, JsonValue const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, URL const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, Dictionary const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, File const&);
|
|
|
+
|
|
|
+template<>
|
|
|
+bool encode(Encoder&, Empty const&);
|
|
|
+
|
|
|
+template<Concepts::Vector T>
|
|
|
+bool encode(Encoder& encoder, T const& vector)
|
|
|
+{
|
|
|
+ if (!encoder.encode(static_cast<u64>(vector.size())))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ for (auto const& value : vector) {
|
|
|
+ if (!encoder.encode(value))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template<Concepts::HashMap T>
|
|
|
+bool encode(Encoder& encoder, T const& hashmap)
|
|
|
+{
|
|
|
+ if (!encoder.encode(static_cast<u32>(hashmap.size())))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ for (auto it : hashmap) {
|
|
|
+ if (!encoder.encode(it.key))
|
|
|
+ return false;
|
|
|
+ if (!encoder.encode(it.value))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template<Concepts::SharedSingleProducerCircularQueue T>
|
|
|
+bool encode(Encoder& encoder, T const& queue)
|
|
|
+{
|
|
|
+ return encoder.encode(IPC::File { queue.fd() });
|
|
|
+}
|
|
|
+
|
|
|
+template<Concepts::Optional T>
|
|
|
+bool encode(Encoder& encoder, T const& optional)
|
|
|
+{
|
|
|
+ if (!encoder.encode(optional.has_value()))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (optional.has_value())
|
|
|
+ return encoder.encode(optional.value());
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template<Concepts::Variant T>
|
|
|
+bool encode(Encoder& encoder, T const& variant)
|
|
|
+{
|
|
|
+ if (!encoder.encode(variant.index()))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return variant.visit([&](auto const& value) {
|
|
|
+ return encoder.encode(value);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// This must be last so that it knows about the above specializations.
|
|
|
+template<typename T>
|
|
|
+bool Encoder::encode(T const& value)
|
|
|
+{
|
|
|
+ return IPC::encode(*this, value);
|
|
|
+}
|
|
|
+
|
|
|
}
|