remove old Result + move everything over to new Result

This commit is contained in:
HJfod 2022-11-28 17:42:19 +02:00
parent 5b3fb508e3
commit 63749320a3
30 changed files with 504 additions and 684 deletions

View file

@ -47,7 +47,7 @@ namespace geode::core {
inline Result<> remove(HookHandle const& handle) {
impl::removeHook(handle);
return Ok<>();
return Ok();
}
}
}

View file

@ -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, ...) \

View file

@ -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())); \
} \
}
}

View file

@ -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())); \
} \
}
}

View file

@ -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;

View file

@ -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");

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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());
}
}

View file

@ -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;
}
}

View file

@ -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();

View file

@ -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());
}
}
}

View file

@ -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();

View file

@ -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() {

View file

@ -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");
}
}

View file

@ -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

View file

@ -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");
}
}

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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",

View file

@ -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) {}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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());
}
}
}

View file

@ -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 {

View file

@ -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);
});
}

View file

@ -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());
}
}

View file

@ -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;

View file

@ -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);
}