mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-01 07:40:18 -04:00
Result stuff
- add NewResult - deprecate and nodiscard old Result - silence some warnings
This commit is contained in:
parent
a85823a322
commit
1dad98b235
11 changed files with 346 additions and 21 deletions
loader
include/Geode
src
hooks
index
internal/windows
load
ui/internal/list
|
@ -175,13 +175,13 @@ namespace geode {
|
|||
void setValue(ValueType const& value) {
|
||||
m_value = value;
|
||||
if constexpr (std::is_base_of_v<IMinMax<ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainMinMax(m_value);
|
||||
(void)static_cast<Class*>(this)->constrainMinMax(m_value);
|
||||
}
|
||||
if constexpr (std::is_base_of_v<IOneOf<Class, ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainOneOf(m_value);
|
||||
(void)static_cast<Class*>(this)->constrainOneOf(m_value);
|
||||
}
|
||||
if constexpr (std::is_base_of_v<IMatch<Class, ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainMatch(m_value);
|
||||
(void)static_cast<Class*>(this)->constrainMatch(m_value);
|
||||
}
|
||||
this->valueChanged();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ if constexpr (
|
|||
wrap::functionName<Derived, types::pure##pure_index>::uuid != nullptr && \
|
||||
(void*)wrap::functionName<Base, types::pure##pure_index>::uuid != (void*)wrap::functionName<Derived, types::pure##pure_index>::uuid \
|
||||
) { \
|
||||
Mod::get()->addHook<wrap::functionName<Derived, types::pure##pure_index>::value, convention>( \
|
||||
(void)Mod::get()->addHook<wrap::functionName<Derived, types::pure##pure_index>::value, convention>( \
|
||||
#className "::" #functionName, \
|
||||
(void*)addresses::address##addr_index() \
|
||||
); \
|
||||
|
|
315
loader/include/Geode/utils/NewResult.hpp
Normal file
315
loader/include/Geode/utils/NewResult.hpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace geode {
|
||||
namespace {
|
||||
struct AnyType {
|
||||
explicit AnyType() = delete;
|
||||
};
|
||||
|
||||
template<class V, class RV>
|
||||
concept ConvertibleToResult =
|
||||
std::is_convertible_v<
|
||||
std::remove_reference_t<V>,
|
||||
std::remove_reference_t<RV>
|
||||
> || std::is_same_v<
|
||||
std::remove_reference_t<V>,
|
||||
std::remove_reference_t<RV>
|
||||
>;
|
||||
|
||||
using DefaultValue = std::monostate;
|
||||
using DefaultError = std::string;
|
||||
}
|
||||
|
||||
template<class T = DefaultValue, class E = DefaultError>
|
||||
class [[nodiscard]] NewResult {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<E>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> ||
|
||||
std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<error_type> ||
|
||||
std::is_move_constructible_v<error_type>,
|
||||
"E must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
std::variant<value_type, error_type> m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return std::holds_alternative<value_type>(m_value);
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return std::holds_alternative<error_type>(m_value);
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value)
|
||||
requires std::is_copy_constructible_v<value_type>
|
||||
: m_value(value) {}
|
||||
explicit NewResult(value_type&& value)
|
||||
requires std::is_move_constructible_v<value_type>
|
||||
: m_value(std::forward<value_type>(value)) {}
|
||||
|
||||
explicit NewResult(error_type const& value)
|
||||
requires std::is_copy_constructible_v<error_type>
|
||||
: m_value(value) {}
|
||||
explicit NewResult(error_type&& value)
|
||||
requires std::is_move_constructible_v<error_type>
|
||||
: m_value(std::forward<error_type>(value)) {}
|
||||
|
||||
NewResult(NewResult<T, E> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
= default;
|
||||
|
||||
NewResult(NewResult<T, E>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type> ||
|
||||
!std::is_copy_constructible_v<error_type>
|
||||
) = default;
|
||||
|
||||
template<class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E>
|
||||
NewResult(NewResult<T2, E2> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
: m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template<class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E>
|
||||
NewResult(NewResult<T2, E2>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type> ||
|
||||
!std::is_copy_constructible_v<error_type>
|
||||
) : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template<class T2>
|
||||
requires ConvertibleToResult<T2, T>
|
||||
NewResult(NewResult<T2, AnyType> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
: NewResult(value_type(other.unwrap())) {}
|
||||
|
||||
template<class E2>
|
||||
requires ConvertibleToResult<E2, E>
|
||||
NewResult(NewResult<AnyType, E2> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
: m_value(std::forward<E2>(other.unwrapErr())) {}
|
||||
|
||||
template<class T2>
|
||||
requires ConvertibleToResult<T2, T>
|
||||
NewResult(NewResult<T2, AnyType>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type> ||
|
||||
!std::is_copy_constructible_v<error_type>
|
||||
) : m_value(other.unwrap()) {}
|
||||
|
||||
template<class E2>
|
||||
requires ConvertibleToResult<E2, E>
|
||||
NewResult(NewResult<AnyType, E2>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type> ||
|
||||
!std::is_copy_constructible_v<error_type>
|
||||
) : NewResult(std::forward<error_type>(other.unwrapErr())) {}
|
||||
|
||||
value_type unwrap() const
|
||||
requires std::is_copy_constructible_v<value_type>
|
||||
{
|
||||
return std::get<value_type>(m_value);
|
||||
}
|
||||
|
||||
value_type&& unwrap()
|
||||
requires (!std::is_copy_constructible_v<value_type>)
|
||||
{
|
||||
return std::move(std::get<value_type>(m_value));
|
||||
}
|
||||
|
||||
error_type unwrapErr() const
|
||||
requires std::is_copy_constructible_v<error_type>
|
||||
{
|
||||
return std::get<error_type>(m_value);
|
||||
}
|
||||
|
||||
error_type&& unwrapErr()
|
||||
requires (!std::is_copy_constructible_v<error_type>)
|
||||
{
|
||||
return std::move(std::get<error_type>(m_value));
|
||||
}
|
||||
|
||||
explicit operator bool() const requires (
|
||||
!std::is_same_v<T, bool> &&
|
||||
!std::is_same_v<E, bool>
|
||||
) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class [[nodiscard]] NewResult<T, T> {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<T>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> ||
|
||||
std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
bool m_success;
|
||||
value_type m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return m_success;
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return !m_success;
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value, bool success)
|
||||
requires std::is_copy_constructible_v<value_type>
|
||||
: m_value(value), m_success(success) {}
|
||||
|
||||
explicit NewResult(value_type&& value, bool success)
|
||||
requires std::is_move_constructible_v<value_type>
|
||||
: m_value(std::forward<value_type>(value)), m_success(success) {}
|
||||
|
||||
NewResult(NewResult<T, T> const& other)
|
||||
requires std::is_copy_constructible_v<value_type> = default;
|
||||
|
||||
NewResult(NewResult<T, T>&& other)
|
||||
requires (!std::is_copy_constructible_v<value_type>) = default;
|
||||
|
||||
template<class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T>
|
||||
NewResult(NewResult<T2, E2> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type>
|
||||
: m_value(other.isOk() ? other.unwrap() : other.unwrapErr()),
|
||||
m_success(other.isOk()) {}
|
||||
|
||||
template<class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T>
|
||||
NewResult(NewResult<T2, E2>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type>
|
||||
) : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()),
|
||||
m_success(other.isOk()) {}
|
||||
|
||||
template<class T2>
|
||||
requires ConvertibleToResult<T2, T>
|
||||
NewResult(NewResult<T2, AnyType> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type>
|
||||
: NewResult(value_type(other.unwrap()), true) {}
|
||||
|
||||
template<class E2>
|
||||
requires ConvertibleToResult<E2, E>
|
||||
NewResult(NewResult<AnyType, E2> const& other)
|
||||
requires
|
||||
std::is_copy_constructible_v<value_type>
|
||||
: NewResult(error_type(other.unwrapErr()), false) {}
|
||||
|
||||
template<class T2>
|
||||
requires ConvertibleToResult<T2, T>
|
||||
NewResult(NewResult<T2, AnyType>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type>
|
||||
) : NewResult(std::forward<value_type>(other.unwrap()), true) {}
|
||||
|
||||
template<class E2>
|
||||
requires ConvertibleToResult<E2, T>
|
||||
NewResult(NewResult<AnyType, E2>&& other)
|
||||
requires (
|
||||
!std::is_copy_constructible_v<value_type>
|
||||
) : NewResult(std::forward<error_type>(other.unwrapErr()), false) {}
|
||||
|
||||
value_type unwrap() const
|
||||
requires std::is_copy_constructible_v<value_type>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
value_type&& unwrap()
|
||||
requires (!std::is_copy_constructible_v<value_type>)
|
||||
{
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
error_type unwrapErr() const
|
||||
requires std::is_copy_constructible_v<error_type>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
error_type&& unwrapErr()
|
||||
requires (!std::is_copy_constructible_v<error_type>)
|
||||
{
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
explicit operator bool() const requires (
|
||||
!std::is_same_v<T, bool>
|
||||
) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T = DefaultValue, class E = AnyType>
|
||||
requires std::is_copy_constructible_v<T>
|
||||
NewResult<T, E> NewOk(T value = T()) {
|
||||
return NewResult<T, E>(value);
|
||||
}
|
||||
|
||||
template<class T = DefaultValue, class E = AnyType>
|
||||
requires (!std::is_copy_constructible_v<T>)
|
||||
NewResult<T, E> NewOk(T&& value) {
|
||||
return NewResult<T, E>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
template<class E = DefaultError, class T = AnyType>
|
||||
requires std::is_copy_constructible_v<E>
|
||||
NewResult<T, E> NewErr(E error = E()) {
|
||||
return NewResult<T, E>(error);
|
||||
}
|
||||
|
||||
template<class E = DefaultError, class T = AnyType>
|
||||
requires (!std::is_copy_constructible_v<E>)
|
||||
NewResult<T, E> NewErr(E&& error) {
|
||||
return NewResult<T, E>(std::forward<E>(error));
|
||||
}
|
||||
|
||||
#define GEODE_UNWRAP_INTO(into, ...) \
|
||||
auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__);\
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) {\
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr()));\
|
||||
}\
|
||||
into = std::move(GEODE_CONCAT(res_, __LINE__).unwrap())
|
||||
|
||||
#define GEODE_UNWRAP(...) \
|
||||
{ auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__);\
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) {\
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr()));\
|
||||
} }
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <string_view>
|
||||
#include "types.hpp"
|
||||
#include "NewResult.hpp"
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
|
@ -26,7 +27,7 @@ namespace geode {
|
|||
* @authors Matcool, HJfod
|
||||
*/
|
||||
template <class T = no_result, class E = std::string>
|
||||
class Result {
|
||||
class [[nodiscard, deprecated("Result's implementation will be replaced with geode::NewResult later")]] Result {
|
||||
protected:
|
||||
bool success;
|
||||
union {
|
||||
|
@ -109,7 +110,7 @@ namespace geode {
|
|||
* Convert to bool
|
||||
* @example if (result) { <handle success> } else { <handle failure> }
|
||||
*/
|
||||
operator bool() const { return this->success; }
|
||||
explicit operator bool() const { return this->success; }
|
||||
|
||||
/**
|
||||
* Create a success result
|
||||
|
@ -130,7 +131,7 @@ namespace geode {
|
|||
* @returns Successful Result
|
||||
*/
|
||||
template <class T = no_result>
|
||||
Result<T> Ok(T value = T()) {
|
||||
Result<T> [[nodiscard, deprecated("Result's implementation will be replaced with geode::NewResult later")]] Ok(T value = T()) {
|
||||
return Result<T>::ok(value);
|
||||
}
|
||||
|
||||
|
@ -141,7 +142,7 @@ namespace geode {
|
|||
* @returns Errorful Result
|
||||
*/
|
||||
template <class E = std::string>
|
||||
struct Err {
|
||||
struct [[nodiscard, deprecated("Result's implementation will be replaced with geode::NewResult later")]] Err {
|
||||
const E _value;
|
||||
Err(const TypeIdentityType<E> value) : _value(value) {}
|
||||
template <class T>
|
||||
|
|
|
@ -37,7 +37,7 @@ static CCEGLView* CCEGLView_CCEGLView(CCEGLView* self) {
|
|||
}
|
||||
|
||||
$execute {
|
||||
Mod::get()->addHook<&CCEGLView_CCEGLView, Thiscall>("CCEGLView::CCEGLView", CCEGLVIEW_CON_ADDR);
|
||||
(void)Mod::get()->addHook<&CCEGLView_CCEGLView, Thiscall>("CCEGLView::CCEGLView", CCEGLVIEW_CON_ADDR);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -150,7 +150,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
|||
// different sha
|
||||
if (force || currentCommitSHA != upcomingCommitSHA) {
|
||||
// save new sha in file
|
||||
utils::file::writeString(indexDir / "current", upcomingCommitSHA);
|
||||
(void)utils::file::writeString(indexDir / "current", upcomingCommitSHA);
|
||||
|
||||
web::AsyncWebRequest()
|
||||
.join("index-download")
|
||||
|
@ -643,7 +643,7 @@ InstallItems::CallbackID InstallItems::start(
|
|||
auto item = Index::get()->getKnownItem(inst);
|
||||
|
||||
auto indexDir = Loader::get()->getGeodeDirectory() / "index";
|
||||
file::createDirectoryAll(indexDir / "temp");
|
||||
(void)file::createDirectoryAll(indexDir / "temp");
|
||||
auto tempFile = indexDir / "temp" / item.m_download.m_filename;
|
||||
|
||||
m_downloaded.push_back(tempFile);
|
||||
|
|
|
@ -257,11 +257,11 @@ static void printMods(std::ostream& stream) {
|
|||
|
||||
static LONG WINAPI exceptionHandler(LPEXCEPTION_POINTERS info) {
|
||||
// make sure crashlog directory exists
|
||||
utils::file::createDirectoryAll(crashlog::getCrashLogDirectory());
|
||||
(void)utils::file::createDirectoryAll(crashlog::getCrashLogDirectory());
|
||||
|
||||
// add a file to let Geode know on next launch that it crashed previously
|
||||
// this could also be done by saving a loader setting or smth but eh.
|
||||
utils::file::writeBinary(
|
||||
(void)utils::file::writeBinary(
|
||||
crashlog::getCrashLogDirectory() + "/last-crashed", {}
|
||||
);
|
||||
|
||||
|
|
|
@ -362,7 +362,10 @@ bool Loader::setup() {
|
|||
log::debug("Setting up Loader...");
|
||||
|
||||
this->createDirectories();
|
||||
this->loadSettings();
|
||||
auto sett = this->loadSettings();
|
||||
if (!sett) {
|
||||
log::warn("Unable to load loader settings: {}", sett.error());
|
||||
}
|
||||
this->refreshMods();
|
||||
|
||||
m_isSetup = true;
|
||||
|
|
|
@ -48,7 +48,7 @@ Mod::Mod(ModInfo const& info) {
|
|||
}
|
||||
|
||||
Mod::~Mod() {
|
||||
this->unload();
|
||||
(void)this->unload();
|
||||
}
|
||||
|
||||
Result<> Mod::loadSettings() {
|
||||
|
@ -217,14 +217,14 @@ Result<> Mod::load() {
|
|||
if (m_implicitLoadFunc) {
|
||||
auto r = m_implicitLoadFunc(this);
|
||||
if (!r) {
|
||||
this->unloadPlatformBinary();
|
||||
(void)this->unloadPlatformBinary();
|
||||
RETURN_LOAD_ERR("Implicit mod entry point returned an error");
|
||||
}
|
||||
}
|
||||
if (m_loadFunc) {
|
||||
auto r = m_loadFunc(this);
|
||||
if (!r) {
|
||||
this->unloadPlatformBinary();
|
||||
(void)this->unloadPlatformBinary();
|
||||
RETURN_LOAD_ERR("Mod entry point returned an error");
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ bool Mod::updateDependencyStates() {
|
|||
}
|
||||
if (dep.isUnresolved()) {
|
||||
m_resolved = false;
|
||||
this->unload();
|
||||
(void)this->unload();
|
||||
hasUnresolved = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,10 @@ Result<ModInfo> ModInfo::createFromFile(ghc::filesystem::path const& path) {
|
|||
auto info = res.value();
|
||||
info.m_path = path;
|
||||
if (path.has_parent_path()) {
|
||||
info.addSpecialFiles(path.parent_path());
|
||||
auto err = info.addSpecialFiles(path.parent_path());
|
||||
if (!err) {
|
||||
return Err(err.error());
|
||||
}
|
||||
}
|
||||
return Ok(info);
|
||||
} catch(std::exception& e) {
|
||||
|
@ -245,7 +248,10 @@ Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path)
|
|||
auto info = res.value();
|
||||
info.m_path = path;
|
||||
|
||||
info.addSpecialFiles(unzip);
|
||||
auto err = info.addSpecialFiles(unzip);
|
||||
if (!err) {
|
||||
return Err(err.error());
|
||||
}
|
||||
|
||||
return Ok(info);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ static bool tryOrAlert(Result<T> const& res, const char* title) {
|
|||
if (!res) {
|
||||
FLAlertLayer::create(title, res.error(), "OK")->show();
|
||||
}
|
||||
return res;
|
||||
return res.is_value();
|
||||
}
|
||||
|
||||
ModCell::ModCell(const char* name, CCSize size) :
|
||||
|
|
Loading…
Add table
Reference in a new issue