111 lines
2.9 KiB
C++
111 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include <Orange/Core/Log.h>
|
|
#include <Orange/Core/AlignedStorage.h>
|
|
#include <Orange/Core/Traits.h>
|
|
|
|
namespace orange
|
|
{
|
|
using ErrorCodeBaseType = int32_t;
|
|
|
|
enum class BasicErrorCode : ErrorCodeBaseType
|
|
{
|
|
Invalid = -1,
|
|
Failed = -2,
|
|
NotFound = -3,
|
|
|
|
Success = 0,
|
|
};
|
|
|
|
template <typename T, typename ErrorCode = BasicErrorCode, ErrorCode SuccessCode = BasicErrorCode::Success, ErrorCode InvalidCode = BasicErrorCode::Invalid, ErrorCode DefaultFail = BasicErrorCode::Failed>
|
|
class Result
|
|
{
|
|
public:
|
|
~Result() { Destroy(); }
|
|
|
|
T* Get()
|
|
{
|
|
Assert(IsSuccess());
|
|
if (!IsSuccess())
|
|
return nullptr;
|
|
|
|
return &RefUnsafe();
|
|
}
|
|
|
|
const T* Get() const
|
|
{
|
|
Assert(IsSuccess());
|
|
if (!IsSuccess())
|
|
return nullptr;
|
|
|
|
return &RefUnsafe();
|
|
}
|
|
|
|
bool IsSuccess() const { return static_cast<int32_t>(m_error) >= 0; }
|
|
|
|
operator bool() const { return IsSuccess(); }
|
|
|
|
T* operator ->() { return Get(); }
|
|
const T* operator ->() const { return Get(); }
|
|
|
|
T& operator *() { return *Get(); }
|
|
const T& operator *() const { return *Get(); }
|
|
|
|
static Result Error(ErrorCode code = DefaultFail)
|
|
{
|
|
Result res;
|
|
res.MakeError(code);
|
|
return res;
|
|
}
|
|
|
|
template <typename... Args>
|
|
static Result Success(Args&&... args)
|
|
{
|
|
Result res;
|
|
res.Create(Forward<Args>(args)...);
|
|
res.MakeSuccess();
|
|
return res;
|
|
}
|
|
|
|
ErrorCode Code() const { return m_error; }
|
|
|
|
template <typename OtherResult>
|
|
static Result ForwardError(OtherResult& x)
|
|
{
|
|
return Error(x.Code());
|
|
}
|
|
|
|
protected:
|
|
Result() = default;
|
|
|
|
template <typename... Args>
|
|
Result& Create(Args&&... args)
|
|
{
|
|
Assert(!m_created);
|
|
m_created = true;
|
|
new(reinterpret_cast<void*>(&m_data)) T{ Forward<Args>(args)... };
|
|
return *this;
|
|
}
|
|
|
|
void Destroy()
|
|
{
|
|
if (m_created)
|
|
{
|
|
RefUnsafe().~T();
|
|
m_created = false;
|
|
}
|
|
}
|
|
|
|
Result& MakeError(ErrorCode code) { m_error = code; return *this; }
|
|
Result& MakeSuccess() { m_error = SuccessCode; return *this; }
|
|
|
|
T& RefUnsafe() { return *reinterpret_cast< T*>(&m_data); }
|
|
const T& RefUnsafe() const { return *reinterpret_cast<const T*>(&m_data); }
|
|
|
|
friend T;
|
|
AlignedStorage<sizeof(T), alignof(T)> m_data;
|
|
ErrorCode m_error = InvalidCode;
|
|
bool m_created = false;
|
|
};
|
|
}
|