diff --git a/loader/include/Geode/hook-core/Hook.hpp b/loader/include/Geode/hook-core/Hook.hpp index 5bf488d3..abc3db28 100644 --- a/loader/include/Geode/hook-core/Hook.hpp +++ b/loader/include/Geode/hook-core/Hook.hpp @@ -47,7 +47,7 @@ namespace geode::core { inline Result<> remove(HookHandle const& handle) { impl::removeHook(handle); - return Ok<>(); + return Ok(); } } } \ No newline at end of file diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp index 59078be0..05fb66d2 100644 --- a/loader/include/Geode/loader/Setting.hpp +++ b/loader/include/Geode/loader/Setting.hpp @@ -81,7 +81,7 @@ namespace geode { #define GEODE_INT_PARSE_SETTING_IMPL(obj, func, ...) \ if constexpr (std::is_base_of_v<__VA_ARGS__, Class>) { \ auto r = std::static_pointer_cast<Class>(res)->func(obj); \ - if (!r) return Err(r.error()); \ + if (!r) return Err(r.unwrapErr()); \ } #define GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(func, ...) \ diff --git a/loader/include/Geode/utils/NewResult.hpp b/loader/include/Geode/utils/NewResult.hpp deleted file mode 100644 index 84eed72d..00000000 --- a/loader/include/Geode/utils/NewResult.hpp +++ /dev/null @@ -1,277 +0,0 @@ -#pragma once - -#include "../DefaultInclude.hpp" - -#include <string> -#include <string_view> -#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 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> const& other) - - requires std::is_copy_constructible_v<value_type> : - NewResult(error_type(other.unwrapErr()), false) {} - - 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())); \ - } \ - } -} diff --git a/loader/include/Geode/utils/Result.hpp b/loader/include/Geode/utils/Result.hpp index 1f7971cc..11b4c816 100644 --- a/loader/include/Geode/utils/Result.hpp +++ b/loader/include/Geode/utils/Result.hpp @@ -1,176 +1,303 @@ #pragma once -#include "NewResult.hpp" -#include "types.hpp" +#include "../DefaultInclude.hpp" -#include <Geode/DefaultInclude.hpp> +#include <string> #include <string_view> +#include <variant> +#include <fmt/format.h> namespace geode { - /** - * @struct no_result - * The default value of a Result. - * Represents a Result that has no - * data to carry on Success, but - * may still return extended - * error information on failure. - */ - struct no_result {}; - - /** - * @class Result - * Represents an optional value with an - * associated error state and -information. - * Use the Ok<T> and Err<T> classes to - * create Result(s). - * @param T Success result value type - * @param E Error message type - * @authors Matcool, HJfod - */ - template <class T = no_result, class E = std::string> - class [[nodiscard]] Result { - protected: - bool success; - - union { - T my_value; - E error_msg; + namespace { + struct AnyType { + explicit AnyType() = delete; }; - Result(const T value) : success(true), my_value(value) {} + 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>>; - Result(const E error, int dummy) : success(false), error_msg(error) {} - - public: - /** - * Destructor - */ - ~Result() { - if (success) { - if (std::is_destructible<T>::value) { - my_value.~T(); - } - } - else { - if (std::is_destructible<E>::value) { - error_msg.~E(); - } - } - } - - /** - * Copy another Result of the same type - */ - Result(Result<T, E> const& other) { - if (other.success) { - this->success = true; - new (&this->my_value) T(other.value()); - } - else { - this->success = false; - new (&this->error_msg) E(other.error()); - } - } - - /** - * Copy another Result of a convertible type - */ - template <class T2, class E2> - Result(Result<T2, E2> const& other) { - if (other.is_value()) { - this->success = true; - if constexpr (!std::is_same<T, no_result>::value) { - new (&this->my_value) T(other.value()); - } - } - else { - this->success = false; - new (&this->error_msg) E(other.error()); - } - } - - /** - * Check if Result was errorful - * @returns True if errorful - */ - bool is_error() const { - return !success; - } - - /** - * Check if Result was succesful - * @returns True if succesful - */ - bool is_value() const { - return success; - } - - /** - * Get the success value of a Result - * @returns Value - */ - auto value() const { - return my_value; - } - - /** - * Get the error message of a Result - * @returns Error - */ - auto error() const { - return error_msg; - } - - /** - * Convert to bool - * @example if (result) { <handle success> } else { <handle failure> } - */ - explicit operator bool() const { - return this->success; - } - - /** - * Create a success result - * @param value Value - */ - static auto ok(const T value) { - return Result<T>(value); - } - - /** - * Create an error result - * @param error Error information - */ - static auto err(E error) { - return Result<T>(error, 0); - } - }; - - /** - * Create a succesful Result with a value - * @param value The value. If none is provided, the type will be no_result - * @returns Successful Result - */ - template <class T = no_result> - [[nodiscard]] Result<T> Ok(T value = T()) { - return Result<T>::ok(value); + using DefaultValue = std::monostate; + using DefaultError = std::string; } - /** - * @class Err - * Create an errorful Result with an error message - * @param value Error message - * @returns Errorful Result - */ - template <class E = std::string> - struct [[nodiscard]] Err { - const E _value; + template <class T = DefaultValue, class E = DefaultError> + class [[nodiscard]] Result { + public: + using value_type = std::remove_reference_t<T>; + using error_type = std::remove_reference_t<E>; - Err(TypeIdentityType<E> const value) : _value(value) {} + // 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!" + ); - template <class T> - operator Result<T, E>() const { - return Result<T, E>::err(_value); + 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); + } + + template<class ... Args> + Result<T, std::string> expect(const char* str, Args&&... args) { + if (isErr()) { + return Result(fmt::format(str, std::forward<Args>(args)...)); + } else { + return this; + } + } + + explicit Result(value_type const& value + ) requires std::is_copy_constructible_v<value_type> : m_value(value) {} + + explicit Result(value_type&& value) requires std::is_move_constructible_v<value_type> : + m_value(std::forward<value_type>(value)) {} + + explicit Result(error_type const& value + ) requires std::is_copy_constructible_v<error_type> : m_value(value) {} + + explicit Result(error_type&& value) requires std::is_move_constructible_v<error_type> : + m_value(std::forward<error_type>(value)) {} + + Result(Result<T, E> const& other) requires std::is_copy_constructible_v<value_type> && + std::is_copy_constructible_v<error_type> + = default; + + Result(Result<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> Result( + Result<T2, E2> const& other + ) + + requires std::is_copy_constructible_v<value_type> && + std::is_copy_constructible_v<error_type> + { + if (other.isOk()) { + m_value = other.unwrap(); + } else { + m_value = other.unwrapErr(); + } + } + + template <class T2, class E2> + requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> Result( + Result<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> Result(Result<T2, AnyType> const& other) + + requires std::is_copy_constructible_v<value_type> && + std::is_copy_constructible_v<error_type> : Result(value_type(other.unwrap())) {} + + template <class E2> + requires ConvertibleToResult<E2, E> Result(Result<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> Result(Result<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> Result(Result<AnyType, E2>&& other) + + requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) : + Result(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]] Result<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; + } + + template<class ... Args> + Result<T, std::string> expect(const char* str, Args&&... args) { + if (isErr()) { + return Result(fmt::format(str, std::forward<Args>(args)...), false); + } else { + return *this; + } + } + + explicit Result(value_type const& value, bool success) requires + std::is_copy_constructible_v<value_type> : + m_value(value), + m_success(success) {} + + explicit Result(value_type&& value, bool success) requires + std::is_move_constructible_v<value_type> : + m_value(std::forward<value_type>(value)), + m_success(success) {} + + Result(Result<T, T> const& other) requires std::is_copy_constructible_v<value_type> + = default; + + Result(Result<T, T>&& other + ) requires(!std::is_copy_constructible_v<value_type>) = default; + + template <class T2, class E2> + requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> Result( + Result<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> Result( + Result<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> Result(Result<T2, AnyType> const& other) + + requires std::is_copy_constructible_v<value_type> : + Result(value_type(other.unwrap()), true) {} + + template <class T2> + requires ConvertibleToResult<T2, T> Result(Result<T2, AnyType>&& other) + + requires(!std::is_copy_constructible_v<value_type>) : + Result(std::forward<value_type>(other.unwrap()), true) {} + + template <class E2> + requires ConvertibleToResult<E2, T> Result(Result<AnyType, E2> const& other) + + requires std::is_copy_constructible_v<value_type> : + Result(error_type(other.unwrapErr()), false) {} + + template <class E2> + requires ConvertibleToResult<E2, T> Result(Result<AnyType, E2>&& other) + + requires(!std::is_copy_constructible_v<value_type>) : + Result(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> Result<T, E> Ok(T value = T()) { + return Result<T, E>(value); + } + + template <class T = DefaultValue, class E = AnyType> + + requires(!std::is_copy_constructible_v<T>) Result<T, E> Ok(T&& value) { + return Result<T, E>(std::forward<T>(value)); + } + + template <class E = DefaultError, class T = AnyType> + + requires std::is_copy_constructible_v<E> Result<T, E> Err(E error = E()) { + return Result<T, E>(error); + } + + template <class E = DefaultError, class T = AnyType> + + requires(!std::is_copy_constructible_v<E>) Result<T, E> Err(E&& error) { + return Result<T, E>(std::forward<E>(error)); + } + +#define GEODE_UNWRAP_INTO(into, ...) \ + auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \ + if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \ + return Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \ + } \ + into = std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrap()) + +#define GEODE_UNWRAP(...) \ + { \ + auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \ + if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \ + return Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \ + } \ + } } diff --git a/loader/include/Geode/utils/fetch.hpp b/loader/include/Geode/utils/fetch.hpp index b9fd6f60..0950bd25 100644 --- a/loader/include/Geode/utils/fetch.hpp +++ b/loader/include/Geode/utils/fetch.hpp @@ -3,6 +3,7 @@ #include "../DefaultInclude.hpp" #include "Result.hpp" #include "json.hpp" +#include "types.hpp" #include <fs/filesystem.hpp> #include <mutex> @@ -46,10 +47,10 @@ namespace geode::utils::web { */ template <class Json = nlohmann::json> Result<Json> fetchJSON(std::string const& url) { - auto res = fetch(url); - if (!res) return Err(res.error()); + std::string res; + GEODE_UNWRAP_INTO(res, fetch(url)); try { - return Ok(Json::parse(res.value())); + return Ok(Json::parse(res)); } catch (std::exception& e) { return Err(e.what()); @@ -309,10 +310,10 @@ namespace geode::utils::web { handle](SentAsyncWebRequest& req, byte_array const& arr) { auto conv = converter(arr); if (conv) { - handle(conv.value()); + handle(conv.unwrap()); } else { - req.error("Unable to convert value: " + conv.error()); + req.error("Unable to convert value: " + conv.unwrapErr()); } }; return m_request; diff --git a/loader/src/hooks/save.cpp b/loader/src/hooks/save.cpp index 6c67759f..dc486006 100644 --- a/loader/src/hooks/save.cpp +++ b/loader/src/hooks/save.cpp @@ -10,7 +10,7 @@ struct SaveLoader : Modify<SaveLoader, AppDelegate> { auto r = Loader::get()->saveData(); if (!r) { - log::log(Severity::Error, Loader::getInternalMod(), "{}", r.error()); + log::log(Severity::Error, Loader::getInternalMod(), "{}", r.unwrapErr()); } log::log(Severity::Info, Loader::getInternalMod(), "Saved"); diff --git a/loader/src/index/Index.cpp b/loader/src/index/Index.cpp index a073ae0f..32bf78f2 100644 --- a/loader/src/index/Index.cpp +++ b/loader/src/index/Index.cpp @@ -20,12 +20,12 @@ template <class Json = nlohmann::json> static Result<Json> readJSON(ghc::filesystem::path const& path) { - auto indexJsonData = utils::file::readString(path); - if (!indexJsonData) { - return Err("Unable to read " + path.string()); - } + GEODE_UNWRAP_INTO( + std::string indexJsonData, + utils::file::readString(path).expect("Unable to read {}", path.string()) + ); try { - return Ok(Json::parse(indexJsonData.value())); + return Ok(Json::parse(indexJsonData)); } catch (std::exception& e) { return Err("Error parsing JSON: " + std::string(e.what())); @@ -110,7 +110,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) { if (ghc::filesystem::exists(indexDir / "current")) { auto data = utils::file::readString(indexDir / "current"); if (data) { - currentCommitSHA = data.value(); + currentCommitSHA = data.unwrap(); } } @@ -128,7 +128,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) { if (upcomingCommitSHA == "") { auto err = this->updateIndexFromLocalCache(); if (!err) { - RETURN_ERROR(err.error()); + RETURN_ERROR(err.unwrapErr()); } m_upToDate = true; @@ -162,13 +162,13 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) { // unzip new index auto unzip = file::unzipTo(indexDir / "index.zip", indexDir); if (!unzip) { - RETURN_ERROR(unzip.error()); + RETURN_ERROR(unzip.unwrapErr()); } // update index auto err = this->updateIndexFromLocalCache(); if (!err) { - RETURN_ERROR(err.error()); + RETURN_ERROR(err.unwrapErr()); } m_upToDate = true; @@ -190,7 +190,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) { else { auto err = this->updateIndexFromLocalCache(); if (!err) { - RETURN_ERROR(err.error()); + RETURN_ERROR(err.unwrapErr()); } m_upToDate = true; @@ -214,10 +214,10 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) { if (ghc::filesystem::exists(dir / "index.json")) { auto readJson = readJSON(dir / "index.json"); if (!readJson) { - log::warn("Error reading index.json: {}, skipping", readJson.error()); + log::warn("Error reading index.json: {}, skipping", readJson.unwrapErr()); return; } - auto json = readJson.value(); + auto json = readJson.unwrap(); if (!json.is_object()) { log::warn("[index.json] is not an object, skipping"); return; @@ -225,10 +225,10 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) { auto infoRes = ModInfo::createFromFile(dir / "mod.json"); if (!infoRes) { - log::warn("{}: {}, skipping", dir, infoRes.error()); + log::warn("{}: {}, skipping", dir, infoRes.unwrapErr()); return; } - auto info = infoRes.value(); + auto info = infoRes.unwrap(); // make sure only latest version is present in index auto old = std::find_if(m_items.begin(), m_items.end(), [info](IndexItem const& item) { @@ -283,7 +283,7 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) { log::warn("[index.json].categories is not an array, skipping"); return; } - item.m_categories = json["categories"].get<std::unordered_set<std::string>>(); + item.m_categories = json["categories"].template get<std::unordered_set<std::string>>(); m_categories.insert(item.m_categories.begin(), item.m_categories.end()); } } @@ -305,7 +305,7 @@ Result<> Index::updateIndexFromLocalCache() { // load geode.json (index settings) if (auto baseIndexJson = readJSON(baseIndexDir / "geode.json")) { - auto json = baseIndexJson.value(); + auto json = baseIndexJson.unwrap(); auto checker = JsonChecker(json); checker.root("[index/geode.json]").obj().has("featured").into(m_featured); } @@ -440,11 +440,8 @@ Result<InstallHandle> Index::installItems(std::vector<IndexItem> const& items) { "the Geode developers - this should not happen, ever." ); } - auto list = checkDependenciesForItem(item); - if (!list) { - return Err(list.error()); - } - ranges::push(ids, list.value()); + GEODE_UNWRAP_INTO(auto list, checkDependenciesForItem(item)); + ranges::push(ids, list); } auto ret = std::make_shared<InstallItems>(std::unordered_set(ids.begin(), ids.end())); m_installations.insert(ret); @@ -636,7 +633,7 @@ InstallItems::CallbackID InstallItems::start(ItemInstallCallback callback, bool .then([this, replaceFiles, item, inst, indexDir, tempFile](auto) { // check for 404 auto notFound = utils::file::readString(tempFile); - if (notFound && notFound.value() == "Not Found") { + if (notFound && notFound.unwrap() == "Not Found") { try { ghc::filesystem::remove(tempFile); } diff --git a/loader/src/internal/InternalLoader.cpp b/loader/src/internal/InternalLoader.cpp index 23eeb19e..e5ad867e 100644 --- a/loader/src/internal/InternalLoader.cpp +++ b/loader/src/internal/InternalLoader.cpp @@ -110,7 +110,7 @@ void InternalLoader::downloadLoaderResources(IndexUpdateCallback callback) { if (!unzip) { if (callback) callback( - UpdateStatus::Failed, "Unable to unzip new resources: " + unzip.error(), 0 + UpdateStatus::Failed, "Unable to unzip new resources: " + unzip.unwrapErr(), 0 ); return; } diff --git a/loader/src/internal/InternalMod.cpp b/loader/src/internal/InternalMod.cpp index b3002bd9..c814fd2a 100644 --- a/loader/src/internal/InternalMod.cpp +++ b/loader/src/internal/InternalMod.cpp @@ -12,17 +12,17 @@ static ModInfo getInternalModInfo() { try { auto json = ModJson::parse(LOADER_MOD_JSON); auto infoRes = ModInfo::create(json); - if (infoRes.is_error()) { + if (infoRes.isErr()) { InternalLoader::platformMessageBox( "Fatal Internal Error", - "Unable to parse loader mod.json: \"" + infoRes.error() + + "Unable to parse loader mod.json: \"" + infoRes.unwrapErr() + "\"\n" "This is a fatal internal error in the loader, please " "contact Geode developers immediately!" ); exit(1); } - auto info = infoRes.value(); + auto info = infoRes.unwrap(); info.m_details = LOADER_ABOUT_MD; info.m_supportInfo = SUPPORT_INFO; info.m_supportsDisabling = false; @@ -50,7 +50,7 @@ InternalMod::InternalMod() : Mod(getInternalModInfo()) { auto sett = this->loadSettings(); if (!sett) { - log::log(Severity::Error, this, "{}", sett.error()); + log::log(Severity::Error, this, "{}", sett.unwrapErr()); } } diff --git a/loader/src/load/Hook.cpp b/loader/src/load/Hook.cpp index 6997d148..d673a6e6 100644 --- a/loader/src/load/Hook.cpp +++ b/loader/src/load/Hook.cpp @@ -33,18 +33,18 @@ Result<> Mod::enableHook(Hook* hook) { log::debug("Enabling hook at function {}", hook->m_displayName); this->m_hooks.push_back(hook); hook->m_enabled = true; - hook->m_handle = res.value(); - return Ok<>(); + hook->m_handle = res.unwrap(); + return Ok(); } else { - return Err<>( + return Err( "Unable to create hook at " + std::to_string(reinterpret_cast<uintptr_t>(hook->m_address)) ); } - return Err<>("Hook already has a handle"); + return Err("Hook already has a handle"); } - return Ok<>(); + return Ok(); } Result<> Mod::disableHook(Hook* hook) { @@ -52,11 +52,11 @@ Result<> Mod::disableHook(Hook* hook) { if (geode::core::hook::remove(hook->m_handle)) { log::debug("Disabling hook at function {}", hook->m_displayName); hook->m_enabled = false; - return Ok<>(); + return Ok(); } - return Err<>("Unable to remove hook"); + return Err("Unable to remove hook"); } - return Ok<>(); + return Ok(); } Result<> Mod::removeHook(Hook* hook) { @@ -73,7 +73,7 @@ Result<Hook*> Mod::addHook(Hook* hook) { auto res = this->enableHook(hook); if (!res) { delete hook; - return Err<>("Can't create hook"); + return Err("Can't create hook"); } } else { @@ -88,7 +88,7 @@ bool InternalLoader::loadHooks() { for (auto const& hook : internalHooks()) { auto res = hook.mod->addHook(hook.hook); if (!res) { - log::log(Severity::Error, hook.mod, "{}", res.error()); + log::log(Severity::Error, hook.mod, "{}", res.unwrapErr()); thereWereErrors = true; } } diff --git a/loader/src/load/Loader.cpp b/loader/src/load/Loader.cpp index f124ea11..00445cfc 100644 --- a/loader/src/load/Loader.cpp +++ b/loader/src/load/Loader.cpp @@ -184,17 +184,17 @@ size_t Loader::loadModsFromDirectory( loadedCount++; // check for dependencies - if (!res.value()->hasUnresolvedDependencies()) { - log::debug("Successfully loaded {}", res.value()); + if (!res.unwrap()->hasUnresolvedDependencies()) { + log::debug("Successfully loaded {}", res.unwrap()); } else { - log::error("{} has unresolved dependencies", res.value()); + log::error("{} has unresolved dependencies", res.unwrap()); } } else { // something went wrong - log::error("{}", res.error()); - m_erroredMods.push_back({ entry.path().string(), res.error() }); + log::error("{}", res.unwrapErr()); + m_erroredMods.push_back({ entry.path().string(), res.unwrapErr() }); } } @@ -213,8 +213,8 @@ size_t Loader::refreshMods() { auto res = this->loadModFromFile(path.string()); if (!res) { // something went wrong - log::error("{}", res.error()); - m_erroredMods.push_back({ path.string(), res.error() }); + log::error("{}", res.unwrapErr()); + m_erroredMods.push_back({ path.string(), res.unwrapErr() }); } } } @@ -245,7 +245,7 @@ Result<> Loader::saveData() { for (auto& [_, mod] : m_mods) { auto r = mod->saveData(); if (!r) { - log::warn("Unable to save data for mod \"{}\": {}", mod->getID(), r.error()); + log::warn("Unable to save data for mod \"{}\": {}", mod->getID(), r.unwrapErr()); } } return Ok(); @@ -257,7 +257,7 @@ Result<> Loader::loadData() { for (auto& [_, mod] : m_mods) { auto r = mod->loadData(); if (!r) { - log::warn("Unable to load data for mod \"{}\": {}", mod->getID(), r.error()); + log::warn("Unable to load data for mod \"{}\": {}", mod->getID(), r.unwrapErr()); } } return Ok(); @@ -277,10 +277,7 @@ Result<> Loader::saveSettings() { json["early-load"] = m_loadedSettings.m_earlyLoadMods; // save loader settings - auto saveIS = InternalMod::get()->saveSettings(); - if (!saveIS) { - return Err(saveIS.error()); - } + GEODE_UNWRAP(InternalMod::get()->saveSettings()); // save info alerts InternalLoader::get()->saveInfoAlerts(json); @@ -298,12 +295,9 @@ Result<> Loader::loadSettings() { } // read mods.json - auto read = utils::file::readString(path); - if (!read) { - return read; - } + GEODE_UNWRAP_INTO(auto read, utils::file::readString(path)); try { - auto json = nlohmann::json::parse(read.value()); + auto json = nlohmann::json::parse(read); auto checker = JsonChecker(json); auto root = checker.root("[loader settings]").obj(); root.has("early-load").into(m_loadedSettings.m_earlyLoadMods); @@ -400,7 +394,7 @@ bool Loader::setup() { this->createDirectories(); auto sett = this->loadData(); if (!sett) { - log::warn("Unable to load loader settings: {}", sett.error()); + log::warn("Unable to load loader settings: {}", sett.unwrapErr()); } this->refreshMods(); diff --git a/loader/src/load/Mod.cpp b/loader/src/load/Mod.cpp index 3ad11f18..9705447d 100644 --- a/loader/src/load/Mod.cpp +++ b/loader/src/load/Mod.cpp @@ -57,11 +57,10 @@ Result<> Mod::loadSettings() { // Check if settings exist auto settPath = m_saveDirPath / "settings.json"; if (ghc::filesystem::exists(settPath)) { - auto settData = utils::file::readString(settPath); - if (!settData) return settData; + GEODE_UNWRAP_INTO(auto settData, utils::file::readString(settPath)); try { // parse settings.json - auto data = nlohmann::json::parse(settData.value()); + auto data = nlohmann::json::parse(settData); JsonChecker checker(data); auto root = checker.root("[settings.json]"); @@ -91,10 +90,9 @@ Result<> Mod::loadSettings() { // Saved values auto savedPath = m_saveDirPath / "saved.json"; if (ghc::filesystem::exists(savedPath)) { - auto data = utils::file::readString(savedPath); - if (!data) return data; + GEODE_UNWRAP_INTO(auto data, utils::file::readString(savedPath)); try { - m_saved = nlohmann::json::parse(data.value()); + m_saved = nlohmann::json::parse(data); } catch(std::exception& e) { return Err(std::string("Unable to parse saved values: ") + e.what()); } @@ -106,10 +104,9 @@ Result<> Mod::loadSettings() { m_dataStore = m_info.m_defaultDataStore; } else { - auto dsData = utils::file::readString(dsPath); - if (!dsData) return dsData; + GEODE_UNWRAP_INTO(auto dsData, utils::file::readString(dsPath)); try { - m_dataStore = nlohmann::json::parse(dsData.value()); + m_dataStore = nlohmann::json::parse(dsData); } catch (std::exception& e) { return Err(std::string("Unable to parse datastore: ") + e.what()); @@ -190,11 +187,11 @@ Result<> Mod::createTempDir() { ZipFile unzip(m_info.m_path.string()); if (!unzip.isLoaded()) { - return Err<>("Unable to unzip " + m_info.m_path.string()); + return Err("Unable to unzip " + m_info.m_path.string()); } if (!unzip.fileExists(m_info.m_binaryName)) { - return Err<>( + return Err( "Unable to find platform binary under the name \"" + m_info.m_binaryName + "\"" ); } @@ -202,13 +199,13 @@ Result<> Mod::createTempDir() { auto tempDir = Loader::get()->getGeodeDirectory() / GEODE_TEMP_DIRECTORY; if (!ghc::filesystem::exists(tempDir)) { if (!ghc::filesystem::create_directory(tempDir)) { - return Err<>("Unable to create temp directory for mods!"); + return Err("Unable to create temp directory for mods!"); } } auto tempPath = ghc::filesystem::path(tempDir) / m_info.m_id; if (!ghc::filesystem::exists(tempPath) && !ghc::filesystem::create_directories(tempPath)) { - return Err<>("Unable to create temp directory"); + return Err("Unable to create temp directory"); } m_tempDirName = tempPath; @@ -217,7 +214,7 @@ Result<> Mod::createTempDir() { if (path.has_parent_path()) { if (!ghc::filesystem::exists(tempPath / path.parent_path()) && !ghc::filesystem::create_directories(tempPath / path.parent_path())) { - return Err<>( + return Err( "Unable to create directories \"" + path.parent_path().string() + "\"" ); } @@ -225,37 +222,37 @@ Result<> Mod::createTempDir() { unsigned long size; auto data = unzip.getFileData(file, &size); if (!data || !size) { - return Err<>("Unable to read \"" + std::string(file) + "\""); + return Err("Unable to read \"" + std::string(file) + "\""); } auto wrt = utils::file::writeBinary(tempPath / file, byte_array(data, data + size)); - if (!wrt) return Err<>("Unable to write \"" + file + "\": " + wrt.error()); + if (!wrt) return Err("Unable to write \"" + file + "\": " + wrt.unwrapErr()); } m_addResourcesToSearchPath = true; - return Ok<>(tempPath); + return Ok(); } Result<> Mod::load() { if (m_loaded) { - return Ok<>(); + return Ok(); } #define RETURN_LOAD_ERR(str) \ { \ m_loadErrorInfo = str; \ - return Err<>(m_loadErrorInfo); \ + return Err(m_loadErrorInfo); \ } if (!m_tempDirName.string().size()) { auto err = this->createTempDir(); - if (!err) RETURN_LOAD_ERR("Unable to create temp directory: " + err.error()); + if (!err) RETURN_LOAD_ERR("Unable to create temp directory: " + err.unwrapErr()); } if (this->hasUnresolvedDependencies()) { RETURN_LOAD_ERR("Mod has unresolved dependencies"); } auto err = this->loadPlatformBinary(); - if (!err) RETURN_LOAD_ERR(err.error()); + if (!err) RETURN_LOAD_ERR(err.unwrapErr()); if (m_implicitLoadFunc) { auto r = m_implicitLoadFunc(this); if (!r) { @@ -279,20 +276,20 @@ Result<> Mod::load() { ModStateEvent(this, ModEventType::Loaded).post(); auto loadRes = this->loadData(); if (!loadRes) { - log::warn("Unable to load data for \"{}\": {}", m_info.m_id, loadRes.error()); + log::warn("Unable to load data for \"{}\": {}", m_info.m_id, loadRes.unwrapErr()); } m_loadErrorInfo = ""; Loader::get()->updateAllDependencies(); - return Ok<>(); + return Ok(); } Result<> Mod::unload() { if (!m_loaded) { - return Ok<>(); + return Ok(); } if (!m_info.m_supportsUnloading) { - return Err<>("Mod does not support unloading"); + return Err("Mod does not support unloading"); } auto saveRes = this->saveData(); @@ -314,7 +311,7 @@ Result<> Mod::unload() { for (auto const& patch : m_patches) { if (!patch->restore()) { - return Err<>("Unable to restore patch at " + std::to_string(patch->getAddress())); + return Err("Unable to restore patch at " + std::to_string(patch->getAddress())); } delete patch; } @@ -326,17 +323,17 @@ Result<> Mod::unload() { } m_loaded = false; Loader::get()->updateAllDependencies(); - return Ok<>(); + return Ok(); } Result<> Mod::enable() { if (!m_loaded) { - return Err<>("Mod is not loaded"); + return Err("Mod is not loaded"); } if (m_enableFunc) { if (!m_enableFunc()) { - return Err<>("Mod enable function returned false"); + return Err("Mod enable function returned false"); } } @@ -349,23 +346,23 @@ Result<> Mod::enable() { for (auto const& patch : m_patches) { if (!patch->apply()) { - return Err<>("Unable to apply patch at " + std::to_string(patch->getAddress())); + return Err("Unable to apply patch at " + std::to_string(patch->getAddress())); } } m_enabled = true; - return Ok<>(); + return Ok(); } Result<> Mod::disable() { if (!m_info.m_supportsDisabling) { - return Err<>("Mod does not support disabling"); + return Err("Mod does not support disabling"); } if (m_disableFunc) { if (!m_disableFunc()) { - return Err<>("Mod disable function returned false"); + return Err("Mod disable function returned false"); } } @@ -378,13 +375,13 @@ Result<> Mod::disable() { for (auto const& patch : m_patches) { if (!patch->restore()) { - return Err<>("Unable to restore patch at " + std::to_string(patch->getAddress())); + return Err("Unable to restore patch at " + std::to_string(patch->getAddress())); } } m_enabled = false; - return Ok<>(); + return Ok(); } Result<> Mod::uninstall() { @@ -397,13 +394,13 @@ Result<> Mod::uninstall() { } } if (!ghc::filesystem::remove(m_info.m_path)) { - return Err<>( + return Err( "Unable to delete mod's .geode file! " "This might be due to insufficient permissions - " "try running GD as administrator." ); } - return Ok<>(); + return Ok(); } bool Mod::isUninstalled() const { @@ -435,13 +432,13 @@ bool Mod::updateDependencyStates() { auto r = dep.m_mod->load(); if (!r) { dep.m_state = ModResolveState::Unloaded; - log::log(Severity::Error, dep.m_mod, "{}", r.error()); + log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr()); } else { auto r = dep.m_mod->enable(); if (!r) { dep.m_state = ModResolveState::Disabled; - log::log(Severity::Error, dep.m_mod, "{}", r.error()); + log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr()); } } } @@ -471,12 +468,12 @@ bool Mod::updateDependencyStates() { log::debug("Resolved & loading {}", m_info.m_id); auto r = this->load(); if (!r) { - log::error("{} Error loading: {}", this, r.error()); + log::error("{} Error loading: {}", this, r.unwrapErr()); } else { auto r = this->enable(); if (!r) { - log::error("{} Error enabling: {}", this, r.error()); + log::error("{} Error enabling: {}", this, r.unwrapErr()); } } } diff --git a/loader/src/load/ModInfo.cpp b/loader/src/load/ModInfo.cpp index fc032c2b..f090cd5e 100644 --- a/loader/src/load/ModInfo.cpp +++ b/loader/src/load/ModInfo.cpp @@ -17,12 +17,6 @@ Result<ModInfo> ModInfo::createFromSchemaV010(ModJson const& rawJson) { auto json = rawJson; info.m_rawJSON = rawJson; -#define PROPAGATE(err) \ - { \ - auto err__ = err; \ - if (!err__) return Err(err__.error()); \ - } - JsonChecker checker(json); auto root = checker.root("[mod.json]").obj(); @@ -59,9 +53,7 @@ Result<ModInfo> ModInfo::createFromSchemaV010(ModJson const& rawJson) { } for (auto& [key, value] : root.has("settings").items()) { - auto settRes = Setting::parse(key, value.json()); - PROPAGATE(settRes); - auto sett = settRes.value(); + GEODE_UNWRAP_INTO(auto sett, Setting::parse(key, value.json())); sett->m_modID = info.m_id; info.m_settings.push_back({ key, sett }); } @@ -180,18 +172,12 @@ Result<ModInfo> ModInfo::create(ModJson const& json) { Result<ModInfo> ModInfo::createFromFile(ghc::filesystem::path const& path) { try { - auto read = utils::file::readString(path); - if (!read) return Err(read.error()); + GEODE_UNWRAP_INTO(auto read, utils::file::readString(path)); try { - auto res = ModInfo::create(ModJson::parse(read.value())); - if (!res) return res; - auto info = res.value(); + GEODE_UNWRAP_INTO(auto info, ModInfo::create(ModJson::parse(read))); info.m_path = path; if (path.has_parent_path()) { - auto err = info.addSpecialFiles(path.parent_path()); - if (!err) { - return Err(err.error()); - } + GEODE_UNWRAP(info.addSpecialFiles(path.parent_path())); } return Ok(info); } @@ -207,11 +193,11 @@ Result<ModInfo> ModInfo::createFromFile(ghc::filesystem::path const& path) { Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path) { ZipFile unzip(path.string()); if (!unzip.isLoaded()) { - return Err<>("\"" + path.string() + "\": Unable to unzip"); + return Err("\"" + path.string() + "\": Unable to unzip"); } // Check if mod.json exists in zip if (!unzip.fileExists("mod.json")) { - return Err<>("\"" + path.string() + "\" is missing mod.json"); + return Err("\"" + path.string() + "\" is missing mod.json"); } // Read mod.json & parse if possible unsigned long readSize = 0; @@ -225,7 +211,7 @@ Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path) } catch (std::exception const& e) { delete[] read; - return Err<>(e.what()); + return Err(e.what()); } delete[] read; @@ -240,15 +226,12 @@ Result<ModInfo> ModInfo::createFromGeodeFile(ghc::filesystem::path const& path) auto res = ModInfo::create(json); if (!res) { - return Err("\"" + path.string() + "\" - " + res.error()); + return Err("\"" + path.string() + "\" - " + res.unwrapErr()); } - auto info = res.value(); + auto info = res.unwrap(); info.m_path = path; - auto err = info.addSpecialFiles(unzip); - if (!err) { - return Err(err.error()); - } + GEODE_UNWRAP(info.addSpecialFiles(unzip)); return Ok(info); } @@ -276,9 +259,9 @@ Result<> ModInfo::addSpecialFiles(ghc::filesystem::path const& dir) { if (ghc::filesystem::exists(dir / file)) { auto data = file::readString(dir / file); if (!data) { - return Err("Unable to read \"" + file + "\": " + data.error()); + return Err("Unable to read \"" + file + "\": " + data.unwrapErr()); } - *target = sanitizeDetailsData(data.value()); + *target = sanitizeDetailsData(data.unwrap()); } } return Ok(); diff --git a/loader/src/load/Patch.cpp b/loader/src/load/Patch.cpp index 4147e860..d3d73811 100644 --- a/loader/src/load/Patch.cpp +++ b/loader/src/load/Patch.cpp @@ -26,7 +26,7 @@ Result<Patch*> Mod::patch(void* address, byte_array data) { p->m_patch = data; if (!p->apply()) { delete p; - return Err<>("Unable to enable patch at " + std::to_string(p->getAddress())); + return Err("Unable to enable patch at " + std::to_string(p->getAddress())); } m_patches.push_back(p); return Ok<Patch*>(p); @@ -36,9 +36,9 @@ Result<> Mod::unpatch(Patch* patch) { if (patch->restore()) { ranges::remove(m_patches, patch); delete patch; - return Ok<>(); + return Ok(); } - return Err<>("Unable to restore patch!"); + return Err("Unable to restore patch!"); } bool Patch::apply() { diff --git a/loader/src/load/ios/Mod.mm b/loader/src/load/ios/Mod.mm index f7cbde72..dd2ca74a 100644 --- a/loader/src/load/ios/Mod.mm +++ b/loader/src/load/ios/Mod.mm @@ -38,7 +38,7 @@ Result<> Mod::loadPlatformBinary() { ); if (!this->m_implicitLoadFunc && !this->m_loadFunc) { - return Err<>( + return Err( "Unable to find mod entry point (lacking both implicit & explicit definition)" ); } @@ -48,10 +48,10 @@ Result<> Mod::loadPlatformBinary() { } this->m_platformInfo = new PlatformInfo { dylib }; - return Ok<>(); + return Ok(); } std::string err = (char const*)dlerror(); - return Err<>("Unable to load the DYLIB: dlerror returned (" + err + ")"); + return Err("Unable to load the DYLIB: dlerror returned (" + err + ")"); } Result<> Mod::unloadPlatformBinary() { @@ -67,10 +67,10 @@ Result<> Mod::unloadPlatformBinary() { this->m_saveDataFunc = nullptr; this->m_loadDataFunc = nullptr; this->m_settingUpdatedFunc = nullptr; - return Ok<>(); + return Ok(); } else { - return Err<>("Unable to free library"); + return Err("Unable to free library"); } } diff --git a/loader/src/load/load.cpp b/loader/src/load/load.cpp index f26a4819..55585a0e 100644 --- a/loader/src/load/load.cpp +++ b/loader/src/load/load.cpp @@ -19,30 +19,27 @@ bool Mod::validateID(std::string const& id) { Result<Mod*> Loader::loadModFromFile(std::string const& path) { // load mod.json - auto res = ModInfo::createFromGeodeFile(path); - if (!res) { - return Err(res.error()); - } + GEODE_UNWRAP_INTO(auto json, ModInfo::createFromGeodeFile(path)); // check that a duplicate has not been loaded - if (m_mods.count(res.value().m_id)) { - return Err("Mod with ID \"" + res.value().m_id + "\" has already been loaded!"); + if (m_mods.count(json.m_id)) { + return Err("Mod with ID \"" + json.m_id + "\" has already been loaded!"); } // create and set up Mod instance - auto mod = new Mod(res.value()); + auto mod = new Mod(json); mod->m_saveDirPath = - Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / res.value().m_id; + Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / json.m_id; ghc::filesystem::create_directories(mod->m_saveDirPath); auto sett = mod->loadSettings(); if (!sett) { - log::log(Severity::Error, mod, "{}", sett.error()); + log::log(Severity::Error, mod, "{}", sett.unwrapErr()); } // enable mod if needed mod->m_enabled = Loader::get()->shouldLoadMod(mod->m_info.m_id); - m_mods.insert({ res.value().m_id, mod }); + m_mods.insert({ json.m_id, mod }); mod->updateDependencyStates(); // add mod resources diff --git a/loader/src/load/mac/Mod.cpp b/loader/src/load/mac/Mod.cpp index 735c53f0..6341058d 100644 --- a/loader/src/load/mac/Mod.cpp +++ b/loader/src/load/mac/Mod.cpp @@ -38,7 +38,7 @@ Result<> Mod::loadPlatformBinary() { ); if (!this->m_implicitLoadFunc && !this->m_loadFunc) { - return Err<>( + return Err( "Unable to find mod entry point (lacking both implicit & explicit definition)" ); } @@ -48,10 +48,10 @@ Result<> Mod::loadPlatformBinary() { } this->m_platformInfo = new PlatformInfo { dylib }; - return Ok<>(); + return Ok(); } std::string err = (char const*)dlerror(); - return Err<>("Unable to load the DYLIB: dlerror returned (" + err + ")"); + return Err("Unable to load the DYLIB: dlerror returned (" + err + ")"); } Result<> Mod::unloadPlatformBinary() { @@ -67,10 +67,10 @@ Result<> Mod::unloadPlatformBinary() { this->m_saveDataFunc = nullptr; this->m_loadDataFunc = nullptr; this->m_settingUpdatedFunc = nullptr; - return Ok<>(); + return Ok(); } else { - return Err<>("Unable to free library"); + return Err("Unable to free library"); } } diff --git a/loader/src/load/windows/Mod.cpp b/loader/src/load/windows/Mod.cpp index c75b8d81..684ebad7 100644 --- a/loader/src/load/windows/Mod.cpp +++ b/loader/src/load/windows/Mod.cpp @@ -91,7 +91,7 @@ Result<> Mod::loadPlatformBinary() { ); if (!this->m_implicitLoadFunc && !this->m_loadFunc) { - return Err<>( + return Err( "Unable to find mod entry point (lacking both implicit & explicit definition)" ); } @@ -101,9 +101,9 @@ Result<> Mod::loadPlatformBinary() { } this->m_platformInfo = new PlatformInfo { load }; - return Ok<>(); + return Ok(); } - return Err<>("Unable to load the DLL: " + getLastWinError()); + return Err("Unable to load the DLL: " + getLastWinError()); } Result<> Mod::unloadPlatformBinary() { @@ -113,10 +113,10 @@ Result<> Mod::unloadPlatformBinary() { this->m_implicitLoadFunc = nullptr; this->m_unloadFunc = nullptr; this->m_loadFunc = nullptr; - return Ok<>(); + return Ok(); } else { - return Err<>("Unable to free the DLL: " + getLastWinError()); + return Err("Unable to free the DLL: " + getLastWinError()); } } diff --git a/loader/src/ui/internal/dev/HookListView.cpp b/loader/src/ui/internal/dev/HookListView.cpp index 094cd70e..063328c3 100644 --- a/loader/src/ui/internal/dev/HookListView.cpp +++ b/loader/src/ui/internal/dev/HookListView.cpp @@ -2,7 +2,10 @@ #include <Geode/binding/StatsCell.hpp> #include <Geode/binding/TableView.hpp> +#include <Geode/binding/FLAlertLayer.hpp> +#include <Geode/binding/CCMenuItemToggler.hpp> #include <Geode/utils/casts.hpp> +#include <Geode/loader/Mod.hpp> HookCell::HookCell(char const* name, CCSize size) : TableViewCell(name, size.width, size.height) {} @@ -19,36 +22,36 @@ void HookCell::updateBGColor(int index) { void HookCell::onEnable(CCObject* pSender) { auto toggle = as<CCMenuItemToggler*>(pSender); if (!toggle->isToggled()) { - auto res = this->m_mod->enableHook(this->m_hook); + auto res = m_mod->enableHook(m_hook); if (!res) { FLAlertLayer::create( - nullptr, "Error Enabling Hook", std::string(res.error()), "OK", nullptr, 280.f + nullptr, "Error Enabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f ) ->show(); } } else { - auto res = this->m_mod->disableHook(this->m_hook); + auto res = m_mod->disableHook(m_hook); if (!res) { FLAlertLayer::create( - nullptr, "Error Disabling Hook", std::string(res.error()), "OK", nullptr, 280.f + nullptr, "Error Disabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f ) ->show(); } } - toggle->toggle(!this->m_hook->isEnabled()); + toggle->toggle(!m_hook->isEnabled()); } void HookCell::loadFromHook(Hook* hook, Mod* Mod) { - this->m_hook = hook; - this->m_mod = Mod; + m_hook = hook; + m_mod = Mod; - this->m_mainLayer->setVisible(true); - this->m_backgroundLayer->setOpacity(255); + m_mainLayer->setVisible(true); + m_backgroundLayer->setOpacity(255); auto menu = CCMenu::create(); - menu->setPosition(this->m_width - this->m_height, this->m_height / 2); - this->m_mainLayer->addChild(menu); + menu->setPosition(m_width - m_height, m_height / 2); + m_mainLayer->addChild(menu); auto enableBtn = CCMenuItemToggler::createWithStandardSprites(this, menu_selector(HookCell::onEnable), .6f); @@ -79,10 +82,10 @@ void HookCell::loadFromHook(Hook* hook, Mod* Mod) { if (hook->getDisplayName() != "") moduleName << hook->getDisplayName(); else moduleName << "0x" << std::hex << hook->getAddress(); auto label = CCLabelBMFont::create(moduleName.str().c_str(), "chatFont.fnt"); - label->setPosition(this->m_height / 2, this->m_height / 2); + label->setPosition(m_height / 2, m_height / 2); label->setScale(.7f); label->setAnchorPoint({ .0f, .5f }); - this->m_mainLayer->addChild(label); + m_mainLayer->addChild(label); } HookCell* HookCell::create(char const* key, CCSize size) { @@ -95,25 +98,25 @@ HookCell* HookCell::create(char const* key, CCSize size) { } void HookListView::setupList() { - this->m_itemSeparation = 30.0f; + m_itemSeparation = 30.0f; - if (!this->m_entries->count()) return; + if (!m_entries->count()) return; - this->m_tableView->reloadData(); + m_tableView->reloadData(); - if (this->m_entries->count() == 1) - this->m_tableView->moveToTopWithOffset(this->m_itemSeparation); + if (m_entries->count() == 1) + m_tableView->moveToTopWithOffset(m_itemSeparation); - this->m_tableView->moveToTop(); + m_tableView->moveToTop(); } TableViewCell* HookListView::getListCell(char const* key) { - return HookCell::create(key, CCSize { this->m_width, this->m_itemSeparation }); + return HookCell::create(key, CCSize { m_width, m_itemSeparation }); } void HookListView::loadCell(TableViewCell* cell, unsigned int index) { as<HookCell*>(cell)->loadFromHook( - as<HookItem*>(this->m_entries->objectAtIndex(index))->m_hook, this->m_mod + as<HookItem*>(m_entries->objectAtIndex(index))->m_hook, m_mod ); as<HookCell*>(cell)->updateBGColor(index); } diff --git a/loader/src/ui/internal/info/ModInfoLayer.cpp b/loader/src/ui/internal/info/ModInfoLayer.cpp index 72058096..ea9ae553 100644 --- a/loader/src/ui/internal/info/ModInfoLayer.cpp +++ b/loader/src/ui/internal/info/ModInfoLayer.cpp @@ -448,12 +448,12 @@ void ModInfoLayer::onEnableMod(CCObject* pSender) { if (as<CCMenuItemToggler*>(pSender)->isToggled()) { auto res = m_mod->load(); if (!res) { - FLAlertLayer::create(nullptr, "Error Loading Mod", res.error(), "OK", nullptr)->show(); + FLAlertLayer::create(nullptr, "Error Loading Mod", res.unwrapErr(), "OK", nullptr)->show(); } else { auto res = m_mod->enable(); if (!res) { - FLAlertLayer::create(nullptr, "Error Enabling Mod", res.error(), "OK", nullptr) + FLAlertLayer::create(nullptr, "Error Enabling Mod", res.unwrapErr(), "OK", nullptr) ->show(); } } @@ -461,7 +461,7 @@ void ModInfoLayer::onEnableMod(CCObject* pSender) { else { auto res = m_mod->disable(); if (!res) { - FLAlertLayer::create(nullptr, "Error Disabling Mod", res.error(), "OK", nullptr) + FLAlertLayer::create(nullptr, "Error Disabling Mod", res.unwrapErr(), "OK", nullptr) ->show(); } } @@ -476,9 +476,11 @@ void ModInfoLayer::onRepository(CCObject*) { void ModInfoLayer::onInstallMod(CCObject*) { auto ticketRes = Index::get()->installItem(Index::get()->getKnownItem(m_info.m_id)); if (!ticketRes) { - return FLAlertLayer::create("Unable to install", ticketRes.error(), "OK")->show(); + return FLAlertLayer::create( + "Unable to install", ticketRes.unwrapErr(), "OK" + )->show(); } - m_installation = ticketRes.value(); + m_installation = ticketRes.unwrap(); createQuickPopup( "Install", @@ -626,7 +628,9 @@ void ModInfoLayer::install() { void ModInfoLayer::uninstall() { auto res = m_mod->uninstall(); if (!res) { - return FLAlertLayer::create("Uninstall failed :(", res.error(), "OK")->show(); + return FLAlertLayer::create( + "Uninstall failed :(", res.unwrapErr(), "OK" + )->show(); } auto layer = FLAlertLayer::create( this, "Uninstall complete", diff --git a/loader/src/ui/internal/list/ModListView.cpp b/loader/src/ui/internal/list/ModListView.cpp index b705923c..89c1b05d 100644 --- a/loader/src/ui/internal/list/ModListView.cpp +++ b/loader/src/ui/internal/list/ModListView.cpp @@ -8,6 +8,7 @@ #include <Geode/binding/CCMenuItemSpriteExtra.hpp> #include <Geode/binding/StatsCell.hpp> #include <Geode/binding/TableView.hpp> +#include <Geode/binding/CCMenuItemToggler.hpp> #include <Geode/loader/Mod.hpp> #include <Geode/utils/casts.hpp> #include <Geode/utils/cocos.hpp> @@ -18,9 +19,9 @@ template <class T> static bool tryOrAlert(Result<T> const& res, char const* title) { if (!res) { - FLAlertLayer::create(title, res.error(), "OK")->show(); + FLAlertLayer::create(title, res.unwrapErr(), "OK")->show(); } - return res.is_value(); + return res.isOk(); } ModCell::ModCell(char const* name, CCSize size) : TableViewCell(name, size.width, size.height) {} diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.cpp b/loader/src/ui/internal/settings/GeodeSettingNode.cpp index f26b8f0a..d2bd15a1 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.cpp @@ -120,10 +120,12 @@ void FileSettingNode::onPickFile(CCObject*) { auto setting = std::static_pointer_cast<FileSetting>(m_setting); if (auto path = file::pickFile( file::PickMode::OpenFile, - { file::geodeRoot(), - setting->getFileFilters().value_or(std::vector<file::FilePickOptions::Filter>()) } + { + file::geodeRoot(), + setting->getFileFilters().value_or(std::vector<file::FilePickOptions::Filter>()) + } )) { - m_uncommittedValue = path.value(); + m_uncommittedValue = path.unwrap(); this->valueChanged(true); } } diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.hpp b/loader/src/ui/internal/settings/GeodeSettingNode.hpp index 8ecb456f..a12e7e99 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.hpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.hpp @@ -162,7 +162,7 @@ namespace { auto isValid = std::static_pointer_cast<T>(m_setting)->isValidValue(m_uncommittedValue); if (!isValid) { m_errorLabel->setVisible(true); - m_errorLabel->setString(isValid.error().c_str()); + m_errorLabel->setString(isValid.unwrapErr().c_str()); } else { m_errorLabel->setVisible(false); diff --git a/loader/src/ui/nodes/ColorPickPopup.cpp b/loader/src/ui/nodes/ColorPickPopup.cpp index 51ff57a0..3bfee86e 100644 --- a/loader/src/ui/nodes/ColorPickPopup.cpp +++ b/loader/src/ui/nodes/ColorPickPopup.cpp @@ -209,9 +209,9 @@ void ColorPickPopup::textChanged(CCTextInputNode* input) { case TAG_HEX_INPUT: { if (auto color = cc3bFromHexString(input->getString())) { - m_color.r = color.value().r; - m_color.g = color.value().g; - m_color.b = color.value().b; + m_color.r = color.unwrap().r; + m_color.g = color.unwrap().g; + m_color.b = color.unwrap().b; } } break; diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 1df6f9b9..a3650afd 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -303,10 +303,10 @@ struct MDParser { else { auto color = colorForIdentifier(tag); if (color) { - renderer->pushColor(color.value()); + renderer->pushColor(color.unwrap()); } else { - log::warn("Error parsing color: {}", color.error()); + log::warn("Error parsing color: {}", color.unwrapErr()); } } } diff --git a/loader/src/utils/convert.cpp b/loader/src/utils/convert.cpp index 5a68c093..007fed17 100644 --- a/loader/src/utils/convert.cpp +++ b/loader/src/utils/convert.cpp @@ -42,10 +42,10 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor3B& color) { auto c = cc3bFromHexString(str); if (!c) { throw nlohmann::json::type_error::create( - 0, "Invalid color hex string: " + c.error(), json + 0, "Invalid color hex string: " + c.unwrapErr(), json ); } - color = c.value(); + color = c.unwrap(); } // bad else { @@ -98,10 +98,10 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor4B& color) { auto c = cc4bFromHexString(str); if (!c) { throw nlohmann::json::type_error::create( - 0, "Invalid color hex string: " + c.error(), json + 0, "Invalid color hex string: " + c.unwrapErr(), json ); } - color = c.value(); + color = c.unwrap(); } // bad else { diff --git a/loader/src/utils/fetch.cpp b/loader/src/utils/fetch.cpp index c1416660..9264877f 100644 --- a/loader/src/utils/fetch.cpp +++ b/loader/src/utils/fetch.cpp @@ -367,26 +367,26 @@ AsyncWebRequest::~AsyncWebRequest() { AsyncWebResult<std::monostate> AsyncWebResponse::into(std::ostream& stream) { m_request.m_target = &stream; - return this->as(+[](byte_array const&) { + return this->as(+[](byte_array const&) -> Result<std::monostate> { return Ok(std::monostate()); }); } AsyncWebResult<std::monostate> AsyncWebResponse::into(ghc::filesystem::path const& path) { m_request.m_target = path; - return this->as(+[](byte_array const&) { + return this->as(+[](byte_array const&) -> Result<std::monostate> { return Ok(std::monostate()); }); } AsyncWebResult<std::string> AsyncWebResponse::text() { - return this->as(+[](byte_array const& bytes) { + return this->as(+[](byte_array const& bytes) -> Result<std::string> { return Ok(std::string(bytes.begin(), bytes.end())); }); } AsyncWebResult<byte_array> AsyncWebResponse::bytes() { - return this->as(+[](byte_array const& bytes) { + return this->as(+[](byte_array const& bytes) -> Result<byte_array> { return Ok(bytes); }); } diff --git a/loader/src/utils/file.cpp b/loader/src/utils/file.cpp index 9b8759d8..971c6e9f 100644 --- a/loader/src/utils/file.cpp +++ b/loader/src/utils/file.cpp @@ -1,6 +1,7 @@ #include <Geode/utils/file.hpp> #include <Geode/utils/string.hpp> #include <fstream> +#include <../support/zip_support/ZipUtils.h> USE_GEODE_NAMESPACE(); @@ -89,10 +90,10 @@ Result<> utils::file::writeString(std::string const& path, std::string const& da file << data; file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } #if _WIN32 @@ -103,10 +104,10 @@ Result<> utils::file::writeString(std::wstring const& path, std::string const& d file << data; file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } #endif @@ -121,10 +122,10 @@ Result<> utils::file::writeString(ghc::filesystem::path const& path, std::string file << data; file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } Result<> utils::file::writeBinary(std::string const& path, byte_array const& data) { @@ -134,10 +135,10 @@ Result<> utils::file::writeBinary(std::string const& path, byte_array const& dat file.write(reinterpret_cast<char const*>(data.data()), data.size()); file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } #if _WIN32 @@ -148,10 +149,10 @@ Result<> utils::file::writeBinary(std::wstring const& path, byte_array const& da file.write(reinterpret_cast<char const*>(data.data()), data.size()); file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } #endif @@ -166,74 +167,74 @@ Result<> utils::file::writeBinary(ghc::filesystem::path const& path, byte_array file.write(reinterpret_cast<char const*>(data.data()), data.size()); file.close(); - return Ok<>(); + return Ok(); } file.close(); - return Err<>("Unable to open file"); + return Err("Unable to open file"); } Result<> utils::file::createDirectory(std::string const& path) { try { if (ghc::filesystem::create_directory(path)) { - return Ok<>(); + return Ok(); } } catch (...) { } - return Err<>("Unable to create directory"); + return Err("Unable to create directory"); } Result<> utils::file::createDirectory(ghc::filesystem::path const& path) { try { if (ghc::filesystem::create_directory(path)) { - return Ok<>(); + return Ok(); } } catch (...) { } - return Err<>("Unable to create directory"); + return Err("Unable to create directory"); } Result<> utils::file::createDirectoryAll(std::string const& path) { try { if (ghc::filesystem::create_directories(path)) { - return Ok<>(); + return Ok(); } } catch (...) { } - return Err<>("Unable to create directories"); + return Err("Unable to create directories"); } Result<> utils::file::createDirectoryAll(ghc::filesystem::path const& path) { try { if (ghc::filesystem::create_directories(path)) { - return Ok<>(); + return Ok(); } } catch (...) { } - return Err<>("Unable to create directories"); + return Err("Unable to create directories"); } Result<std::vector<std::string>> utils::file::listFiles(std::string const& path) { - if (!ghc::filesystem::exists(path)) return Err<>("Directory does not exist"); + if (!ghc::filesystem::exists(path)) return Err("Directory does not exist"); std::vector<std::string> res; for (auto const& file : ghc::filesystem::directory_iterator(path)) { res.push_back(file.path().string()); } - return Ok<>(res); + return Ok(res); } Result<std::vector<std::string>> utils::file::listFilesRecursively(std::string const& path) { - if (!ghc::filesystem::exists(path)) return Err<>("Directory does not exist"); + if (!ghc::filesystem::exists(path)) return Err("Directory does not exist"); std::vector<std::string> res; for (auto const& file : ghc::filesystem::recursive_directory_iterator(path)) { res.push_back(file.path().string()); } - return Ok<>(res); + return Ok(res); } Result<> utils::file::unzipTo(ghc::filesystem::path const& from, ghc::filesystem::path const& to) { @@ -274,7 +275,7 @@ Result<> utils::file::unzipTo(ghc::filesystem::path const& from, ghc::filesystem } auto wrt = utils::file::writeBinary(to / file, byte_array(data, data + size)); if (!wrt) { - return Err("Unable to write \"" + (to / file).string() + "\": " + wrt.error()); + return Err("Unable to write \"" + (to / file).string() + "\": " + wrt.unwrapErr()); } } diff --git a/loader/src/utils/windows/nfdwin.cpp b/loader/src/utils/windows/nfdwin.cpp index e3609a6e..fdf0819c 100644 --- a/loader/src/utils/windows/nfdwin.cpp +++ b/loader/src/utils/windows/nfdwin.cpp @@ -235,11 +235,7 @@ Result<> nfdPick( Holder _([&]() { shellItems->Release(); }); - auto res = convShellItems(shellItems); - if (!res) { - return Err(res.error()); - } - *reinterpret_cast<Paths*>(result) = res.value(); + GEODE_UNWRAP_INTO(*reinterpret_cast<Paths*>(result), convShellItems(shellItems)); return Ok(); } break; diff --git a/loader/src/utils/windows/util.cpp b/loader/src/utils/windows/util.cpp index 683f8d8a..840827f0 100644 --- a/loader/src/utils/windows/util.cpp +++ b/loader/src/utils/windows/util.cpp @@ -89,13 +89,10 @@ Result<ghc::filesystem::path> utils::file::pickFile( TURN_INTO_NFDMODE(OpenFile); TURN_INTO_NFDMODE(SaveFile); TURN_INTO_NFDMODE(OpenFolder); - default: return Err("Unknown open mode"); + default: return Err<std::string>("Unknown open mode"); } ghc::filesystem::path path; - auto r = nfdPick(nfdMode, options, &path); - if (!r) { - return Err(r.error()); - } + GEODE_UNWRAP(nfdPick(nfdMode, options, &path)); return Ok(path); } @@ -103,10 +100,7 @@ Result<std::vector<ghc::filesystem::path>> utils::file::pickFiles( file::FilePickOptions const& options ) { std::vector<ghc::filesystem::path> paths; - auto r = nfdPick(NFDMode::OpenFolder, options, &paths); - if (!r) { - return Err(r.error()); - } + GEODE_UNWRAP(nfdPick(NFDMode::OpenFolder, options, &paths)); return Ok(paths); }