KResult.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Assertions.h>
  8. #include <AK/Format.h>
  9. #include <AK/Platform.h>
  10. #include <AK/StdLibExtras.h>
  11. #include <AK/Try.h>
  12. #include <LibC/errno_numbers.h>
  13. namespace Kernel {
  14. enum KSuccessTag {
  15. KSuccess
  16. };
  17. class [[nodiscard]] KResult {
  18. public:
  19. KResult(ErrnoCode error)
  20. : m_error(-error)
  21. {
  22. }
  23. KResult(KSuccessTag)
  24. : m_error(0)
  25. {
  26. }
  27. [[nodiscard]] int error() const { return m_error; }
  28. [[nodiscard]] bool is_success() const { return m_error == 0; }
  29. [[nodiscard]] bool is_error() const { return !is_success(); }
  30. bool operator==(ErrnoCode error) const { return is_error() && m_error == -error; }
  31. bool operator!=(ErrnoCode error) const { return !is_error() || m_error != -error; }
  32. bool operator!=(KSuccessTag) const { return is_error(); }
  33. bool operator==(KSuccessTag) const { return !is_error(); }
  34. private:
  35. template<typename T>
  36. friend class KResultOr;
  37. KResult() = default;
  38. int m_error { 0 };
  39. };
  40. template<typename T>
  41. class [[nodiscard]] KResultOr {
  42. public:
  43. KResultOr(KResult error)
  44. : m_error(error)
  45. , m_is_error(true)
  46. {
  47. }
  48. KResultOr(ErrnoCode error)
  49. : m_error(error)
  50. , m_is_error(true)
  51. {
  52. }
  53. ALWAYS_INLINE KResultOr(T&& value)
  54. : m_have_storage(true)
  55. {
  56. new (&m_storage) T(move(value));
  57. }
  58. ALWAYS_INLINE KResultOr(const T& value)
  59. : m_have_storage(true)
  60. {
  61. new (&m_storage) T(value);
  62. }
  63. template<typename U>
  64. ALWAYS_INLINE KResultOr(U&& value) requires(!IsSame<RemoveCVReference<U>, KResultOr<T>>)
  65. : m_have_storage(true)
  66. {
  67. new (&m_storage) T(forward<U>(value));
  68. }
  69. KResultOr(KResultOr&& other)
  70. {
  71. m_is_error = other.m_is_error;
  72. if (m_is_error) {
  73. m_error = other.m_error;
  74. } else {
  75. if (other.m_have_storage) {
  76. new (&m_storage) T(move(other.value()));
  77. m_have_storage = true;
  78. other.value().~T();
  79. other.m_have_storage = false;
  80. }
  81. }
  82. other.m_is_error = true;
  83. other.m_error = KSuccess;
  84. }
  85. KResultOr& operator=(KResultOr&& other)
  86. {
  87. if (&other == this)
  88. return *this;
  89. if (!m_is_error && m_have_storage) {
  90. value().~T();
  91. m_have_storage = false;
  92. }
  93. m_is_error = other.m_is_error;
  94. if (m_is_error) {
  95. m_error = other.m_error;
  96. } else {
  97. if (other.m_have_storage) {
  98. new (&m_storage) T(move(other.value()));
  99. m_have_storage = true;
  100. other.value().~T();
  101. other.m_have_storage = false;
  102. }
  103. }
  104. other.m_is_error = true;
  105. other.m_error = KSuccess;
  106. return *this;
  107. }
  108. ~KResultOr()
  109. {
  110. if (!m_is_error && m_have_storage)
  111. value().~T();
  112. }
  113. [[nodiscard]] bool is_error() const { return m_is_error; }
  114. [[nodiscard]] ALWAYS_INLINE KResult error() const
  115. {
  116. VERIFY(m_is_error);
  117. return m_error;
  118. }
  119. [[nodiscard]] KResult result() const { return m_is_error ? m_error : KSuccess; }
  120. [[nodiscard]] ALWAYS_INLINE T& value() &
  121. {
  122. VERIFY(!m_is_error);
  123. return *reinterpret_cast<T*>(&m_storage);
  124. }
  125. [[nodiscard]] ALWAYS_INLINE T const& value() const&
  126. {
  127. VERIFY(!m_is_error);
  128. return *reinterpret_cast<T*>(&m_storage);
  129. }
  130. T value() && = delete;
  131. [[nodiscard]] ALWAYS_INLINE T release_value()
  132. {
  133. VERIFY(!m_is_error);
  134. VERIFY(m_have_storage);
  135. T released_value(move(*reinterpret_cast<T*>(&m_storage)));
  136. value().~T();
  137. m_have_storage = false;
  138. return released_value;
  139. }
  140. [[nodiscard]] KResult release_error()
  141. {
  142. VERIFY(m_is_error);
  143. return m_error;
  144. }
  145. private:
  146. union {
  147. alignas(T) char m_storage[sizeof(T)];
  148. KResult m_error;
  149. };
  150. bool m_is_error { false };
  151. bool m_have_storage { false };
  152. };
  153. }
  154. using Kernel::KResult;
  155. using Kernel::KResultOr;
  156. using Kernel::KSuccess;
  157. template<>
  158. struct AK::Formatter<KResult> : Formatter<FormatString> {
  159. void format(FormatBuilder& builder, Kernel::KResult value)
  160. {
  161. if (value.is_error())
  162. return AK::Formatter<FormatString>::format(builder, "KResult({})", value.error());
  163. return AK::Formatter<FormatString>::format(builder, "KResult(success)");
  164. }
  165. };