summaryrefslogtreecommitdiff
path: root/asl/status.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'asl/status.hpp')
-rw-r--r--asl/status.hpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/asl/status.hpp b/asl/status.hpp
index 2e4bae5..4638493 100644
--- a/asl/status.hpp
+++ b/asl/status.hpp
@@ -6,8 +6,77 @@
namespace asl
{
+enum class status_code : uint8_t
+{
+ ok = 0,
+ unknown = 1,
+ internal = 2,
+ runtime = 3,
+ invalid_argument = 4,
+};
+
class status
{
+ void* m_payload{};
+
+ static constexpr void* status_to_payload(status_code code)
+ {
+ return code == status_code::ok ? nullptr : bit_cast<void*>(((uintptr_t)code << 1) | 1);
+ }
+
+ static constexpr status_code payload_to_status(void* payload)
+ {
+ return (status_code)(bit_cast<uintptr_t>(payload) >> 1);
+ }
+
+ status_code code_internal() const;
+
+public:
+ constexpr status() = default;
+
+ explicit constexpr status(status_code code)
+ : m_payload{status_to_payload(code)}
+ {}
+
+ status(status_code code, string_view msg);
+
+ constexpr status(status&& other)
+ : m_payload{exchange(other.m_payload, nullptr)}
+ {}
+
+ constexpr status& operator=(status&& other)
+ {
+ if (&other != this)
+ {
+ swap(m_payload, other.m_payload);
+ }
+ return *this;
+ }
+
+ // @Todo Copy constructor & assignment
+
+ constexpr bool ok() const
+ {
+ return m_payload == nullptr || code() == status_code::ok;
+ }
+
+ // NOLINTNEXTLINE(*-explicit-conversions)
+ constexpr operator bool() const { return ok(); }
+
+ constexpr status_code code() const
+ {
+ if (m_payload == nullptr)
+ {
+ return status_code::ok;
+ }
+
+ if ((bit_cast<uintptr_t>(m_payload) & 1) != 0)
+ {
+ return payload_to_status(m_payload);
+ }
+
+ return code_internal();
+ }
};
} // namespace asl