Encoder.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Concepts.h>
  9. #include <AK/HashMap.h>
  10. #include <AK/StdLibExtras.h>
  11. #include <AK/Variant.h>
  12. #include <LibCore/SharedCircularQueue.h>
  13. #include <LibIPC/Concepts.h>
  14. #include <LibIPC/Forward.h>
  15. #include <LibIPC/Message.h>
  16. namespace IPC {
  17. template<typename T>
  18. ErrorOr<void> encode(Encoder&, T const&)
  19. {
  20. static_assert(DependentFalse<T>, "Base IPC::encode() was instantiated");
  21. VERIFY_NOT_REACHED();
  22. }
  23. class Encoder {
  24. public:
  25. explicit Encoder(MessageBuffer& buffer)
  26. : m_buffer(buffer)
  27. {
  28. }
  29. template<typename T>
  30. ErrorOr<void> encode(T const& value);
  31. ErrorOr<void> extend_capacity(size_t capacity)
  32. {
  33. TRY(m_buffer.extend_data_capacity(capacity));
  34. return {};
  35. }
  36. ErrorOr<void> append(u8 const* values, size_t count)
  37. {
  38. TRY(m_buffer.append_data(values, count));
  39. return {};
  40. }
  41. ErrorOr<void> append_file_descriptor(int fd)
  42. {
  43. TRY(m_buffer.append_file_descriptor(fd));
  44. return {};
  45. }
  46. ErrorOr<void> encode_size(size_t size);
  47. private:
  48. MessageBuffer& m_buffer;
  49. };
  50. template<Arithmetic T>
  51. ErrorOr<void> encode(Encoder& encoder, T const& value)
  52. {
  53. TRY(encoder.append(reinterpret_cast<u8 const*>(&value), sizeof(value)));
  54. return {};
  55. }
  56. template<Enum T>
  57. ErrorOr<void> encode(Encoder& encoder, T const& value)
  58. {
  59. return encoder.encode(to_underlying(value));
  60. }
  61. template<>
  62. ErrorOr<void> encode(Encoder&, float const&);
  63. template<>
  64. ErrorOr<void> encode(Encoder&, double const&);
  65. template<>
  66. ErrorOr<void> encode(Encoder&, String const&);
  67. template<>
  68. ErrorOr<void> encode(Encoder&, StringView const&);
  69. template<>
  70. ErrorOr<void> encode(Encoder&, ByteString const&);
  71. template<>
  72. ErrorOr<void> encode(Encoder&, ByteBuffer const&);
  73. template<>
  74. ErrorOr<void> encode(Encoder&, JsonValue const&);
  75. template<>
  76. ErrorOr<void> encode(Encoder&, Duration const&);
  77. template<>
  78. ErrorOr<void> encode(Encoder&, UnixDateTime const&);
  79. template<>
  80. ErrorOr<void> encode(Encoder&, URL const&);
  81. template<>
  82. ErrorOr<void> encode(Encoder&, File const&);
  83. template<>
  84. ErrorOr<void> encode(Encoder&, Empty const&);
  85. template<typename T, size_t N>
  86. ErrorOr<void> encode(Encoder& encoder, Array<T, N> const& array)
  87. {
  88. TRY(encoder.encode_size(array.size()));
  89. for (auto const& value : array)
  90. TRY(encoder.encode(value));
  91. return {};
  92. }
  93. template<Concepts::Vector T>
  94. ErrorOr<void> encode(Encoder& encoder, T const& vector)
  95. {
  96. // NOTE: Do not change this encoding without also updating LibC/netdb.cpp.
  97. TRY(encoder.encode_size(vector.size()));
  98. for (auto const& value : vector)
  99. TRY(encoder.encode(value));
  100. return {};
  101. }
  102. template<Concepts::HashMap T>
  103. ErrorOr<void> encode(Encoder& encoder, T const& hashmap)
  104. {
  105. TRY(encoder.encode_size(hashmap.size()));
  106. for (auto it : hashmap) {
  107. TRY(encoder.encode(it.key));
  108. TRY(encoder.encode(it.value));
  109. }
  110. return {};
  111. }
  112. template<Concepts::SharedSingleProducerCircularQueue T>
  113. ErrorOr<void> encode(Encoder& encoder, T const& queue)
  114. {
  115. return encoder.encode(IPC::File { queue.fd() });
  116. }
  117. template<Concepts::Optional T>
  118. ErrorOr<void> encode(Encoder& encoder, T const& optional)
  119. {
  120. TRY(encoder.encode(optional.has_value()));
  121. if (optional.has_value())
  122. TRY(encoder.encode(optional.value()));
  123. return {};
  124. }
  125. template<Concepts::Variant T>
  126. ErrorOr<void> encode(Encoder& encoder, T const& variant)
  127. {
  128. TRY(encoder.encode(variant.index()));
  129. return variant.visit([&](auto const& value) {
  130. return encoder.encode(value);
  131. });
  132. }
  133. // This must be last so that it knows about the above specializations.
  134. template<typename T>
  135. ErrorOr<void> Encoder::encode(T const& value)
  136. {
  137. return IPC::encode(*this, value);
  138. }
  139. }