Luna/luna/Result.h

238 lines
4.0 KiB
C
Raw Normal View History

2022-11-13 11:20:53 +00:00
#pragma once
#include <Move.h>
#include <PlacementNew.h>
#include <Types.h>
struct Error
{
Error(int err)
{
error = err;
}
int error;
};
template <typename T> class Result
{
public:
Result(const T& value)
{
m_storage.store_reference(value);
m_has_value = true;
m_has_error = false;
}
Result(T&& value)
{
2022-11-13 13:29:15 +00:00
m_storage.store_movable_reference(move(value));
2022-11-13 11:20:53 +00:00
m_has_value = true;
m_has_error = false;
}
Result(const Result<T>& other)
{
if (!other.m_has_error)
{
m_storage.store_reference(other.m_storage.fetch_reference());
m_has_value = true;
m_has_error = false;
}
else
{
m_has_error = true;
m_has_value = false;
m_error = other.m_error;
}
}
Result(Result<T>&& other)
{
if (!other.m_has_error)
{
m_storage.store_movable_reference(move(other.m_storage.fetch_reference()));
m_has_value = true;
m_has_error = false;
}
else
{
m_has_error = true;
m_has_value = false;
m_error = other.m_error;
}
}
Result(const Error& err)
{
m_error = err.error;
m_has_error = true;
m_has_value = false;
}
bool has_error()
{
return m_has_error;
}
bool has_value()
{
return m_has_value;
}
int error()
{
// ensure(has_error());
return m_error;
}
Error release_error()
{
// ensure(has_error());
return {m_error};
}
T value()
{
// ensure(has_value());
return m_storage.fetch_reference();
}
T value_or(T other)
{
if (has_value()) return m_storage.fetch_reference();
return other;
}
T release_value()
{
// ensure(has_value());
T item = m_storage.fetch_reference();
m_has_value = false;
m_storage.destroy();
return move(item);
}
~Result()
{
if (has_value()) m_storage.destroy();
}
private:
struct Storage
{
u8 buffer[sizeof(T)];
T* fetch_ptr()
{
return (T*)buffer;
}
T& fetch_reference()
{
return *fetch_ptr();
}
const T* fetch_ptr() const
{
return (const T*)buffer;
}
const T& fetch_reference() const
{
return *fetch_ptr();
}
void store_ptr(T* ptr)
{
new (buffer) T(*ptr);
}
void store_reference(const T& ref)
{
new (buffer) T(ref);
}
void store_movable_reference(T&& ref)
{
new (buffer) T(ref);
}
void destroy()
{
fetch_reference().~T();
}
};
Storage m_storage;
int m_error;
bool m_has_error;
bool m_has_value;
};
template <> class Result<void>
{
public:
Result()
{
m_has_error = false;
}
Result(const Result<void>& other)
{
m_has_error = other.m_has_error;
m_error = other.m_error;
}
Result(Result<void>&& other)
{
m_has_error = other.m_has_error;
m_error = other.m_error;
}
Result(const Error& err)
{
m_error = err.error;
m_has_error = true;
}
bool has_error()
{
return m_has_error;
}
bool has_value()
{
return !m_has_error;
}
int error()
{
// ensure(has_error());
return m_error;
}
Error release_error()
{
// ensure(has_error());
return {m_error};
}
void value()
{
// ensure(has_value());
return;
}
void release_value()
{
// ensure(has_value());
return;
}
private:
int m_error;
bool m_has_error;
2022-11-13 13:29:15 +00:00
};
// clang-format off
#define err Error{0}
// clang-format on