KResult.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (c) 2018-2020, 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 <LibC/errno_numbers.h>
  12. namespace Kernel {
  13. enum KSuccessTag {
  14. KSuccess
  15. };
  16. class [[nodiscard]] KResult {
  17. public:
  18. KResult(ErrnoCode error)
  19. : m_error(-error)
  20. {
  21. }
  22. KResult(KSuccessTag)
  23. : m_error(0)
  24. {
  25. }
  26. operator int() const { return m_error; }
  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. private:
  31. template<typename T>
  32. friend class KResultOr;
  33. KResult() = default;
  34. int m_error { 0 };
  35. };
  36. template<typename T>
  37. class alignas(T) [[nodiscard]] KResultOr {
  38. public:
  39. KResultOr(KResult error)
  40. : m_error(error)
  41. , m_is_error(true)
  42. {
  43. }
  44. KResultOr(ErrnoCode error)
  45. : m_error(error)
  46. , m_is_error(true)
  47. {
  48. }
  49. ALWAYS_INLINE KResultOr(T&& value)
  50. {
  51. new (&m_storage) T(move(value));
  52. m_have_storage = true;
  53. }
  54. template<typename U>
  55. ALWAYS_INLINE KResultOr(U&& value)
  56. {
  57. new (&m_storage) T(move(value));
  58. m_have_storage = true;
  59. }
  60. KResultOr(KResultOr&& other)
  61. {
  62. m_is_error = other.m_is_error;
  63. if (m_is_error)
  64. m_error = other.m_error;
  65. else {
  66. if (other.m_have_storage) {
  67. new (&m_storage) T(move(other.value()));
  68. m_have_storage = true;
  69. other.value().~T();
  70. other.m_have_storage = false;
  71. }
  72. }
  73. other.m_is_error = true;
  74. other.m_error = KSuccess;
  75. }
  76. KResultOr& operator=(KResultOr&& other)
  77. {
  78. if (&other == this)
  79. return *this;
  80. if (!m_is_error && m_have_storage) {
  81. value().~T();
  82. m_have_storage = false;
  83. }
  84. m_is_error = other.m_is_error;
  85. if (m_is_error)
  86. m_error = other.m_error;
  87. else {
  88. if (other.m_have_storage) {
  89. new (&m_storage) T(move(other.value()));
  90. m_have_storage = true;
  91. other.value().~T();
  92. other.m_have_storage = false;
  93. }
  94. }
  95. other.m_is_error = true;
  96. other.m_error = KSuccess;
  97. return *this;
  98. }
  99. ~KResultOr()
  100. {
  101. if (!m_is_error && m_have_storage)
  102. value().~T();
  103. }
  104. [[nodiscard]] bool is_error() const { return m_is_error; }
  105. [[nodiscard]] ALWAYS_INLINE KResult error() const
  106. {
  107. VERIFY(m_is_error);
  108. return m_error;
  109. }
  110. [[nodiscard]] KResult result() const { return m_is_error ? m_error : KSuccess; }
  111. [[nodiscard]] ALWAYS_INLINE T& value()
  112. {
  113. VERIFY(!m_is_error);
  114. return *reinterpret_cast<T*>(&m_storage);
  115. }
  116. [[nodiscard]] ALWAYS_INLINE const T& value() const
  117. {
  118. VERIFY(!m_is_error);
  119. return *reinterpret_cast<T*>(&m_storage);
  120. }
  121. [[nodiscard]] ALWAYS_INLINE T release_value()
  122. {
  123. VERIFY(!m_is_error);
  124. VERIFY(m_have_storage);
  125. T released_value(move(*reinterpret_cast<T*>(&m_storage)));
  126. value().~T();
  127. m_have_storage = false;
  128. return released_value;
  129. }
  130. private:
  131. union {
  132. alignas(T) char m_storage[sizeof(T)];
  133. KResult m_error;
  134. };
  135. bool m_is_error { false };
  136. bool m_have_storage { false };
  137. };
  138. }
  139. template<>
  140. struct AK::Formatter<Kernel::KResult> : Formatter<int> {
  141. void format(FormatBuilder& builder, Kernel::KResult value)
  142. {
  143. return Formatter<int>::format(builder, value);
  144. }
  145. };