Files
godot/thirdparty/jolt_physics/Jolt/Core/Result.h
noahbackus 9d30169a8d
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
initial commit, 4.5 stable
2025-09-16 20:46:46 -04:00

175 lines
3.6 KiB
C++

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
JPH_NAMESPACE_BEGIN
/// Helper class that either contains a valid result or an error
template <class Type>
class Result
{
public:
/// Default constructor
Result() { }
/// Copy constructor
Result(const Result<Type> &inRHS) :
mState(inRHS.mState)
{
switch (inRHS.mState)
{
case EState::Valid:
new (&mResult) Type (inRHS.mResult);
break;
case EState::Error:
new (&mError) String(inRHS.mError);
break;
case EState::Invalid:
break;
}
}
/// Move constructor
Result(Result<Type> &&inRHS) noexcept :
mState(inRHS.mState)
{
switch (inRHS.mState)
{
case EState::Valid:
new (&mResult) Type (std::move(inRHS.mResult));
break;
case EState::Error:
new (&mError) String(std::move(inRHS.mError));
break;
case EState::Invalid:
break;
}
// Don't reset the state of inRHS, the destructors still need to be called after a move operation
}
/// Destructor
~Result() { Clear(); }
/// Copy assignment
Result<Type> & operator = (const Result<Type> &inRHS)
{
Clear();
mState = inRHS.mState;
switch (inRHS.mState)
{
case EState::Valid:
new (&mResult) Type (inRHS.mResult);
break;
case EState::Error:
new (&mError) String(inRHS.mError);
break;
case EState::Invalid:
break;
}
return *this;
}
/// Move assignment
Result<Type> & operator = (Result<Type> &&inRHS) noexcept
{
Clear();
mState = inRHS.mState;
switch (inRHS.mState)
{
case EState::Valid:
new (&mResult) Type (std::move(inRHS.mResult));
break;
case EState::Error:
new (&mError) String(std::move(inRHS.mError));
break;
case EState::Invalid:
break;
}
// Don't reset the state of inRHS, the destructors still need to be called after a move operation
return *this;
}
/// Clear result or error
void Clear()
{
switch (mState)
{
case EState::Valid:
mResult.~Type();
break;
case EState::Error:
mError.~String();
break;
case EState::Invalid:
break;
}
mState = EState::Invalid;
}
/// Checks if the result is still uninitialized
bool IsEmpty() const { return mState == EState::Invalid; }
/// Checks if the result is valid
bool IsValid() const { return mState == EState::Valid; }
/// Get the result value
const Type & Get() const { JPH_ASSERT(IsValid()); return mResult; }
/// Set the result value
void Set(const Type &inResult) { Clear(); new (&mResult) Type(inResult); mState = EState::Valid; }
/// Set the result value (move value)
void Set(Type &&inResult) { Clear(); new (&mResult) Type(std::move(inResult)); mState = EState::Valid; }
/// Check if we had an error
bool HasError() const { return mState == EState::Error; }
/// Get the error value
const String & GetError() const { JPH_ASSERT(HasError()); return mError; }
/// Set an error value
void SetError(const char *inError) { Clear(); new (&mError) String(inError); mState = EState::Error; }
void SetError(const string_view &inError) { Clear(); new (&mError) String(inError); mState = EState::Error; }
void SetError(String &&inError) { Clear(); new (&mError) String(std::move(inError)); mState = EState::Error; }
private:
union
{
Type mResult; ///< The actual result object
String mError; ///< The error description if the result failed
};
/// State of the result
enum class EState : uint8
{
Invalid,
Valid,
Error
};
EState mState = EState::Invalid;
};
JPH_NAMESPACE_END