update to new result

This commit is contained in:
altalk23 2024-11-04 23:24:20 +03:00
parent 8320cf6057
commit bdb0c99e17
36 changed files with 159 additions and 6391 deletions

View file

@ -237,6 +237,7 @@ endif()
set(MAT_JSON_AS_INTERFACE ON) set(MAT_JSON_AS_INTERFACE ON)
CPMAddPackage("gh:geode-sdk/json#cda9807") CPMAddPackage("gh:geode-sdk/json#cda9807")
CPMAddPackage("gh:geode-sdk/result@1.0.1")
CPMAddPackage("gh:fmtlib/fmt#10.2.1") CPMAddPackage("gh:fmtlib/fmt#10.2.1")
target_compile_definitions(${PROJECT_NAME} INTERFACE MAT_JSON_DYNAMIC=1) target_compile_definitions(${PROJECT_NAME} INTERFACE MAT_JSON_DYNAMIC=1)
@ -296,7 +297,7 @@ target_include_directories(GeodeBindings PUBLIC
${GEODE_LOADER_PATH}/include/Geode/fmod ${GEODE_LOADER_PATH}/include/Geode/fmod
) )
target_link_directories(GeodeBindings PUBLIC ${GEODE_LOADER_PATH}/include/link) target_link_directories(GeodeBindings PUBLIC ${GEODE_LOADER_PATH}/include/link)
target_link_libraries(GeodeBindings PUBLIC fmt TulipHookInclude mat-json) target_link_libraries(GeodeBindings PUBLIC fmt TulipHookInclude mat-json GeodeResult)
target_link_libraries(${PROJECT_NAME} INTERFACE GeodeBindings) target_link_libraries(${PROJECT_NAME} INTERFACE GeodeBindings)
if (NOT EXISTS ${GEODE_BIN_PATH}) if (NOT EXISTS ${GEODE_BIN_PATH})

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "DefaultInclude.hpp" #include "DefaultInclude.hpp"
#include "utils/Result.hpp"
#include "utils/VersionInfo.hpp" #include "utils/VersionInfo.hpp"
#include "utils/ranges.hpp" #include "utils/ranges.hpp"
#include "utils/casts.hpp" #include "utils/casts.hpp"

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include "../utils/Result.hpp" #include <Geode/Result.hpp>
#include "Log.hpp" #include "Log.hpp"
#include "ModEvent.hpp" #include "ModEvent.hpp"
#include "ModMetadata.hpp" #include "ModMetadata.hpp"

View file

@ -2,7 +2,7 @@
#include "../DefaultInclude.hpp" #include "../DefaultInclude.hpp"
#include "../cocos/support/zip_support/ZipUtils.h" #include "../cocos/support/zip_support/ZipUtils.h"
#include "../utils/Result.hpp" #include <Geode/Result.hpp>
#include "../utils/VersionInfo.hpp" #include "../utils/VersionInfo.hpp"
#include "../utils/general.hpp" #include "../utils/general.hpp"

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../utils/Result.hpp" #include <Geode/Result.hpp>
#include "../utils/VersionInfo.hpp" #include "../utils/VersionInfo.hpp"
#include "Types.hpp" #include "Types.hpp"

View file

@ -7,7 +7,7 @@ namespace geode::hook {
/** /**
* Create a calling convention wrapper for a function. * Create a calling convention wrapper for a function.
*/ */
GEODE_DLL tulip::hook::Result<void*> createWrapper( GEODE_DLL Result<void*> createWrapper(
void* address, void* address,
tulip::hook::WrapperMetadata const& metadata tulip::hook::WrapperMetadata const& metadata
) noexcept; ) noexcept;

View file

@ -158,7 +158,7 @@ namespace geode::modifier {
for (auto& [uuid, hook] : m_hooks) { for (auto& [uuid, hook] : m_hooks) {
auto res = Mod::get()->claimHook(hook); auto res = Mod::get()->claimHook(hook);
if (!res) { if (!res) {
log::error("Failed to claim hook {}: {}", hook->getDisplayName(), res.error()); log::error("Failed to claim hook {}: {}", hook->getDisplayName(), res.unwrapErr());
} }
else { else {
added.push_back(uuid); added.push_back(uuid);

View file

@ -4,7 +4,7 @@
#include "../loader/Log.hpp" #include "../loader/Log.hpp"
#include <set> #include <set>
#include <variant> #include <variant>
#include <Geode/utils/Result.hpp> #include <Geode/Result.hpp>
namespace geode { namespace geode {
struct JsonChecker; struct JsonChecker;

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../loader/Hook.hpp" #include "../loader/Hook.hpp"
#include "Result.hpp" #include <Geode/Result.hpp>
namespace geode { namespace geode {
namespace hook { namespace hook {

View file

@ -1,305 +0,0 @@
#pragma once
#include "../DefaultInclude.hpp"
#include "../external/result/result.hpp"
#include <fmt/format.h>
#include <string>
#include <string_view>
#include <type_traits>
#include <variant>
#include <optional>
namespace geode {
namespace impl {
using DefaultValue = std::monostate;
using DefaultError = std::string;
template <class T>
using WrappedResult = std::conditional_t<
std::is_lvalue_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>,
std::remove_const_t<T>>;
template <class E = impl::DefaultError>
class [[nodiscard]] Failure {
public:
WrappedResult<E> m_error;
Failure() = default;
template <class E2>
requires(std::is_constructible_v<E, E2 const&>)
explicit constexpr Failure(E2 const& e) : m_error(e) {}
template <class E2>
requires(std::is_constructible_v<E, E2 &&>)
explicit constexpr Failure(E2&& e) : m_error(std::move(e)) {}
E& error() & noexcept {
return m_error;
}
E const& error() const& noexcept {
return m_error;
}
E&& error() && noexcept {
return static_cast<E&&>(m_error);
}
E const&& error() const&& noexcept {
return static_cast<E&&>(m_error);
}
};
template <class T = impl::DefaultValue>
class [[nodiscard]] Success {
public:
WrappedResult<T> m_value;
Success() = default;
template <class T2>
requires(std::is_constructible_v<T, T2 const&>)
explicit constexpr Success(T2 const& v) : m_value(v) {}
template <class T2>
requires(std::is_constructible_v<T, T2 &&>)
explicit constexpr Success(T2&& v) : m_value(std::forward<T2>(v)) {}
T& value() & noexcept {
return m_value;
}
T const& value() const& noexcept {
return m_value;
}
T&& value() && noexcept {
return static_cast<T&&>(m_value);
}
T const&& value() const&& noexcept {
return static_cast<T&&>(m_value);
}
};
}
template <class T = impl::DefaultValue, class E = impl::DefaultError>
class [[nodiscard]] Result : public cpp::result<T, E> {
public:
using Base = cpp::result<T, E>;
using ValueType = typename Base::value_type;
using ErrorType = typename Base::error_type;
using Base::result;
template <class U>
requires(cpp::detail::result_is_implicit_value_convertible<T, U>::value)
constexpr Result(U&& value) = delete;
template <class E2>
requires(std::is_constructible_v<E, E2 const&>)
constexpr Result(impl::Failure<E2> const& e) : Base(cpp::failure<E>(e.error())) {}
template <class E2>
requires(std::is_constructible_v<E, E2 &&>)
constexpr Result(impl::Failure<E2>&& e) : Base(cpp::failure<E>(std::move(e.error()))) {}
template <class T2>
requires(std::is_constructible_v<T, T2 const&>)
constexpr Result(impl::Success<T2> const& s) : Base(s.value()) {}
template <class T2>
requires(std::is_constructible_v<T, T2 &&>)
constexpr Result(impl::Success<T2>&& s) : Base(std::move(s.value())) {}
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return this->Base::operator bool();
}
[[nodiscard]] constexpr bool isOk() const noexcept {
return this->Base::has_value();
}
[[nodiscard]] constexpr bool isErr() const noexcept {
return this->Base::has_error();
}
[[nodiscard]] constexpr decltype(auto) unwrap() & {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() const& {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() && {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() const&& {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() & {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() const& {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() && {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() const&& {
return this->Base::error();
}
template <class... Args>
requires(std::is_constructible_v<T, T &&>)
[[nodiscard]] Result<T, std::string> expect(std::string const& format, Args&&... args) {
if (this->isErr()) {
return impl::Failure<std::string>(fmt::format(
fmt::runtime(format), std::forward<Args>(args)...,
fmt::arg("error", this->unwrapErr())
));
}
else {
return std::move(*this);
}
}
template <class... Args>
requires(std::is_constructible_v<T, T const&>)
[[nodiscard]] Result<T, std::string> expect(std::string const& format, Args&&... args)
const {
if (this->isErr()) {
return impl::Failure<std::string>(fmt::format(
fmt::runtime(format), std::forward<Args>(args)...,
fmt::arg("error", this->unwrapErr())
));
}
else {
return *this;
}
}
template <class U>
[[nodiscard]] constexpr decltype(auto) unwrapOr(U&& val) && {
return this->Base::value_or(std::forward<U>(val));
}
template <class U>
[[nodiscard]] constexpr decltype(auto) unwrapOr(U&& val) const& {
return this->Base::value_or(std::forward<U>(val));
}
[[nodiscard]] constexpr decltype(auto) unwrapOrDefault() && requires std::is_default_constructible_v<T> {
return this->Base::value_or(T());
}
[[nodiscard]] constexpr decltype(auto) unwrapOrDefault() const& requires std::is_default_constructible_v<T> {
return this->Base::value_or(T());
}
template <class U>
[[nodiscard]] constexpr decltype(auto) errorOr(U&& val) && {
return this->Base::error_or(std::forward<U>(val));
}
template <class U>
[[nodiscard]] constexpr decltype(auto) errorOr(U&& val) const& {
return this->Base::error_or(std::forward<U>(val));
}
/**
* Convert the result into an optional containing the value if Ok, and
* nullopt if Err
*/
[[nodiscard]] constexpr std::optional<T> ok() const& {
if (this->isOk()) {
return this->unwrap();
}
return std::nullopt;
}
/**
* Convert the result into an optional containing the value if Ok, and
* nullopt if Err
*/
[[nodiscard]] constexpr std::optional<T> ok() && {
if (this->isOk()) {
return this->unwrap();
}
return std::nullopt;
}
/**
* Convert the result into an optional containing the error if Err, and
* nullopt if Ok
*/
[[nodiscard]] constexpr std::optional<E> err() const& {
if (this->isErr()) {
return this->unwrapErr();
}
return std::nullopt;
}
/**
* Convert the result into an optional containing the error if Err, and
* nullopt if Ok
*/
[[nodiscard]] constexpr std::optional<E> err() && {
if (this->isErr()) {
return this->unwrapErr();
}
return std::nullopt;
}
/**
* Completely disregard the result. Only recommended if the result is
* inconsequential
*/
constexpr void disregard() && {}
};
template <class T = impl::DefaultValue>
constexpr impl::Success<T> Ok() {
return impl::Success<T>();
}
template <class T>
constexpr impl::Success<T> Ok(T value) {
// DO NOT MAKE THE PARAMETER T&&!!!! THAT WILL CAUSE C++ TO DO UNEXPECTED
// IMPLICIT MOVES FOR EXAMPLE WHEN DOING `Ok(unordered_map.at(value))`
return impl::Success<T>(std::forward<T>(value));
}
template <class E>
constexpr impl::Failure<E> Err(E error) {
return impl::Failure<E>(std::forward<E>(error));
}
template <class... Args>
inline impl::Failure<std::string> Err(std::string const& format, Args&&... args) {
return impl::Failure<std::string>(
fmt::format(fmt::runtime(format), std::forward<Args>(args)...)
);
}
#define GEODE_UNWRAP_INTO(into, ...) \
auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \
if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \
return geode::Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \
} \
into = std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrap())
#define GEODE_UNWRAP(...) \
do { \
auto GEODE_CONCAT(unwrap_res_, __LINE__) = (__VA_ARGS__); \
if (GEODE_CONCAT(unwrap_res_, __LINE__).isErr()) { \
return geode::Err(std::move(GEODE_CONCAT(unwrap_res_, __LINE__).unwrapErr())); \
} \
} while(false)
}

View file

@ -248,7 +248,7 @@ namespace geode {
using Value = T; using Value = T;
using Progress = P; using Progress = P;
using PostResult = std::function<void(Result)>; using PostResult = std::function<void(Result&&)>;
using PostProgress = std::function<void(P)>; using PostProgress = std::function<void(P)>;
using HasBeenCancelled = std::function<bool()>; using HasBeenCancelled = std::function<bool()>;
using Run = std::function<Result(PostProgress, HasBeenCancelled)>; using Run = std::function<Result(PostProgress, HasBeenCancelled)>;

View file

@ -4,7 +4,7 @@
#include <string_view> #include <string_view>
#include <matjson.hpp> #include <matjson.hpp>
#include <tuple> #include <tuple>
#include "../utils/Result.hpp" #include <Geode/Result.hpp>
namespace geode { namespace geode {
enum class VersionCompare { enum class VersionCompare {

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Result.hpp" #include <Geode/Result.hpp>
#include "general.hpp" #include "general.hpp"
#include "../loader/Event.hpp" #include "../loader/Event.hpp"
#include "Task.hpp" #include "Task.hpp"

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Result.hpp" #include <Geode/Result.hpp>
#include "../DefaultInclude.hpp" #include "../DefaultInclude.hpp"
#include <chrono> #include <chrono>
@ -13,6 +13,7 @@
#include <charconv> #include <charconv>
#include <clocale> #include <clocale>
#include <type_traits> #include <type_traits>
#include <fmt/format.h>
namespace geode { namespace geode {
using ByteVector = std::vector<uint8_t>; using ByteVector = std::vector<uint8_t>;
@ -159,6 +160,12 @@ namespace geode {
*/ */
GEODE_DLL float getDisplayFactor(); GEODE_DLL float getDisplayFactor();
} }
template <class... Args>
requires (sizeof...(Args) > 0)
constexpr auto Err(fmt::format_string<Args...> fmt, Args&&... args) {
return Err(fmt::format(fmt, std::forward<Args>(args)...));
}
} }
template<> template<>

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Result.hpp" #include <Geode/Result.hpp>
#include <Geode/DefaultInclude.hpp> #include <Geode/DefaultInclude.hpp>
#include <functional> #include <functional>

View file

@ -2,7 +2,7 @@
#include <Geode/loader/Loader.hpp> // another great circular dependency fix #include <Geode/loader/Loader.hpp> // another great circular dependency fix
#include <matjson.hpp> #include <matjson.hpp>
#include "Result.hpp" #include <Geode/Result.hpp>
#include "Task.hpp" #include "Task.hpp"
#include <chrono> #include <chrono>
#include <optional> #include <optional>

View file

@ -496,20 +496,20 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
thread::setName("Mod Unzip"); thread::setName("Mod Unzip");
log::loadNest(nest); log::loadNest(nest);
auto res = unzipFunction(); auto res = unzipFunction();
auto prevNest = log::saveNest();
log::loadNest(nest);
if (!res) {
this->addProblem({
LoadProblem::Type::UnzipFailed,
node,
res.unwrapErr()
});
log::error("Failed to unzip: {}", res.unwrapErr());
m_refreshingModCount -= 1;
log::loadNest(prevNest);
return;
}
this->queueInMainThread([=, this]() { this->queueInMainThread([=, this]() {
auto prevNest = log::saveNest();
log::loadNest(nest);
if (!res) {
this->addProblem({
LoadProblem::Type::UnzipFailed,
node,
res.unwrapErr()
});
log::error("Failed to unzip: {}", res.unwrapErr());
m_refreshingModCount -= 1;
log::loadNest(prevNest);
return;
}
loadFunction(); loadFunction();
log::loadNest(prevNest); log::loadNest(prevNest);
}); });

View file

@ -7,7 +7,7 @@
#include <Geode/loader/Loader.hpp> #include <Geode/loader/Loader.hpp>
#include <Geode/loader/Log.hpp> #include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp> #include <Geode/loader/Mod.hpp>
#include <Geode/utils/Result.hpp> #include <Geode/Result.hpp>
#include <Geode/utils/map.hpp> #include <Geode/utils/map.hpp>
#include <Geode/utils/ranges.hpp> #include <Geode/utils/ranges.hpp>
#include "ModImpl.hpp" #include "ModImpl.hpp"

View file

@ -51,7 +51,9 @@ Result<> Mod::Impl::setup() {
(void) utils::file::createDirectoryAll(m_saveDirPath); (void) utils::file::createDirectoryAll(m_saveDirPath);
// always create temp dir for all mods, even if disabled, so resources can be loaded // always create temp dir for all mods, even if disabled, so resources can be loaded
GEODE_UNWRAP(this->createTempDir().expect("Unable to create temp dir: {error}")); GEODE_UNWRAP(this->createTempDir().mapErr([](auto const& err) {
return fmt::format("Unable to create temp dir: {}", err);
}));
m_settings = std::make_unique<ModSettingsManager>(m_metadata); m_settings = std::make_unique<ModSettingsManager>(m_metadata);
auto loadRes = this->loadData(); auto loadRes = this->loadData();

View file

@ -307,8 +307,11 @@ Result<ModMetadata> ModMetadata::Impl::create(ModJson const& json) {
if (json.contains("geode") && json["geode"].is_string()) { if (json.contains("geode") && json["geode"].is_string()) {
GEODE_UNWRAP_INTO( GEODE_UNWRAP_INTO(
schema, schema,
VersionInfo::parse(json["geode"].as_string()) VersionInfo::parse(json["geode"].as_string()).mapErr(
.expect("[mod.json] has invalid target loader version: {error}") [](auto const& err) {
return fmt::format("[mod.json] has invalid target loader version: {}", err);
}
)
); );
} }
else { else {
@ -382,7 +385,9 @@ Result<ModMetadata> ModMetadata::Impl::createFromGeodeZip(file::Unzip& unzip) {
// Read mod.json & parse if possible // Read mod.json & parse if possible
GEODE_UNWRAP_INTO( GEODE_UNWRAP_INTO(
auto jsonData, unzip.extract("mod.json").expect("Unable to read mod.json: {error}") auto jsonData, unzip.extract("mod.json").mapErr([](auto const& err) {
return fmt::format("Unable to extract mod.json: {}", err);
})
); );
std::string error; std::string error;
@ -400,7 +405,9 @@ Result<ModMetadata> ModMetadata::Impl::createFromGeodeZip(file::Unzip& unzip) {
auto impl = info.m_impl.get(); auto impl = info.m_impl.get();
impl->m_path = unzip.getPath(); impl->m_path = unzip.getPath();
GEODE_UNWRAP(info.addSpecialFiles(unzip).expect("Unable to add extra files: {error}")); GEODE_UNWRAP(info.addSpecialFiles(unzip).mapErr([](auto const& err) {
return fmt::format("Unable to add extra files: {}", err);
}));
return Ok(info); return Ok(info);
} }
@ -409,7 +416,9 @@ Result<> ModMetadata::Impl::addSpecialFiles(file::Unzip& unzip) {
// unzip known MD files // unzip known MD files
for (auto& [file, target] : this->getSpecialFiles()) { for (auto& [file, target] : this->getSpecialFiles()) {
if (unzip.hasEntry(file)) { if (unzip.hasEntry(file)) {
GEODE_UNWRAP_INTO(auto data, unzip.extract(file).expect("Unable to extract \"{}\"", file)); GEODE_UNWRAP_INTO(auto data, unzip.extract(file).mapErr([&](auto const& err) {
return fmt::format("Unable to extract \"{}\": {}", file, err);
}));
*target = sanitizeDetailsData(std::string(data.begin(), data.end())); *target = sanitizeDetailsData(std::string(data.begin(), data.end()));
} }
} }

View file

@ -8,22 +8,36 @@ using namespace geode::prelude;
// #1 no need to duplicate the built-in settings between all mods // #1 no need to duplicate the built-in settings between all mods
// #2 easier lookup of custom settings if a mod uses another mod's custom setting type // #2 easier lookup of custom settings if a mod uses another mod's custom setting type
namespace {
auto changeToGenerator(auto&& function) {
return [function](
std::string const& key,
std::string const& modID,
matjson::Value const& json
) -> Result<std::shared_ptr<SettingV3>> {
return function(key, modID, json).map([](auto&& ptr) {
return std::shared_ptr<SettingV3>(ptr);
});
};
}
}
class SharedSettingTypesPool final { class SharedSettingTypesPool final {
private: private:
std::unordered_map<std::string, SettingGenerator> m_types; std::unordered_map<std::string, SettingGenerator> m_types;
SharedSettingTypesPool() : m_types({ SharedSettingTypesPool() : m_types({
{ "title", &TitleSetting::parse }, { "title", changeToGenerator(TitleSettingV3::parse) },
{ "bool", &BoolSetting::parse }, { "bool", changeToGenerator(BoolSettingV3::parse) },
{ "int", &IntSetting::parse }, { "int", changeToGenerator(IntSettingV3::parse) },
{ "float", &FloatSetting::parse }, { "float", changeToGenerator(FloatSettingV3::parse) },
{ "string", &StringSetting::parse }, { "string", changeToGenerator(StringSettingV3::parse) },
{ "file", &FileSetting::parse }, { "file", changeToGenerator(FileSettingV3::parse) },
{ "folder", &FileSetting::parse }, { "folder", changeToGenerator(FileSettingV3::parse) },
{ "path", &FileSetting::parse }, { "path", changeToGenerator(FileSettingV3::parse) },
{ "rgb", &Color3BSetting::parse }, { "rgb", changeToGenerator(Color3BSettingV3::parse) },
{ "color", &Color3BSetting::parse }, { "color", changeToGenerator(Color3BSettingV3::parse) },
{ "rgba", &Color4BSetting::parse }, { "rgba", changeToGenerator(Color4BSettingV3::parse) },
}) {} }) {}
public: public:
@ -135,7 +149,7 @@ public:
continue; continue;
} }
if (auto v3 = (*gen)(key, modID, setting.json)) { if (auto v3 = (*gen)(key, modID, setting.json)) {
setting.v3 = *v3; setting.v3 = v3.unwrap();
this->loadSettingValueFromSave(key); this->loadSettingValueFromSave(key);
} }
else { else {

View file

@ -92,8 +92,8 @@ Result<> Patch::Impl::updateBytes(const ByteVector& bytes) {
if (m_enabled) { if (m_enabled) {
auto res = this->disable(); auto res = this->disable();
if (!res) return Err("Failed to update patch: {}", res.unwrapErr()); if (!res) return Err("Failed to update patch: {}", res.unwrapErr());
res = this->enable(); auto res2 = this->enable();
if (!res) return Err("Failed to update patch: {}", res.unwrapErr()); if (!res2) return Err("Failed to update patch: {}", res2.unwrapErr());
} }
return Ok(); return Ok();

View file

@ -152,18 +152,21 @@ namespace enable_if_parsing {
return Ok(); return Ok();
} }
Result<> eval(std::string const& defaultModID) const override { Result<> eval(std::string const& defaultModID) const override {
Result<> err = Ok(); std::optional<std::string> err;
for (auto& comp : components) { for (auto& comp : components) {
auto res = comp->eval(defaultModID); auto res = comp->eval(defaultModID);
if (res) { if (res) {
return Ok(); return Ok();
} }
// Only show first condition that isn't met // Only show first condition that isn't met
if (err.isOk()) { if (!err.has_value()) {
err = Err(res.unwrapErr()); err = res.unwrapErr();
} }
} }
return err; if (err.has_value()) {
return Err(*err);
}
return Ok();
} }
}; };
@ -235,7 +238,10 @@ namespace enable_if_parsing {
auto original = m_index; auto original = m_index;
auto ret = this->nextWord(); auto ret = this->nextWord();
m_index = original; m_index = original;
return ret ? *ret : std::nullopt; if (!ret) {
return std::nullopt;
}
return ret.unwrap();
} }
Result<std::unique_ptr<Component>> nextComponent() { Result<std::unique_ptr<Component>> nextComponent() {
GEODE_UNWRAP_INTO(auto maybeWord, this->nextWord()); GEODE_UNWRAP_INTO(auto maybeWord, this->nextWord());

View file

@ -1,7 +1,9 @@
#include <Geode/loader/Tulip.hpp> #include <Geode/loader/Tulip.hpp>
tulip::hook::Result<void*> geode::hook::createWrapper( using namespace geode::prelude;
Result<void*> geode::hook::createWrapper(
void* address, void* address,
tulip::hook::WrapperMetadata const& metadata tulip::hook::WrapperMetadata const& metadata
) noexcept { ) noexcept {

View file

@ -83,7 +83,7 @@ void updater::fetchLatestGithubRelease(
} }
else { else {
Mod::get()->setSavedValue("last-modified-auto-update-check", response->header("Last-Modified").value_or("")); Mod::get()->setSavedValue("last-modified-auto-update-check", response->header("Last-Modified").value_or(""));
s_latestGithubRelease = *json; s_latestGithubRelease = json.unwrap();
then(*s_latestGithubRelease); then(*s_latestGithubRelease);
} }
} }
@ -141,7 +141,7 @@ void updater::tryDownloadLoaderResources(std::string const& url, bool tryLatestO
// unzip resources zip // unzip resources zip
auto unzip = file::Unzip::create(response->data()); auto unzip = file::Unzip::create(response->data());
if (unzip) { if (unzip) {
auto ok = unzip->extractAllTo(resourcesDir); auto ok = unzip.unwrap().extractAllTo(resourcesDir);
if (ok) { if (ok) {
updater::updateSpecialFiles(); updater::updateSpecialFiles();
ResourceDownloadEvent(UpdateFinished()).post(); ResourceDownloadEvent(UpdateFinished()).post();
@ -308,7 +308,7 @@ void updater::downloadLoaderUpdate(std::string const& url) {
// unzip resources zip // unzip resources zip
auto unzip = file::Unzip::create(response->data()); auto unzip = file::Unzip::create(response->data());
if (unzip) { if (unzip) {
auto ok = unzip->extractAllTo(targetDir); auto ok = unzip.unwrap().extractAllTo(targetDir);
if (ok) { if (ok) {
s_isNewUpdateDownloaded = true; s_isNewUpdateDownloaded = true;
LoaderUpdateEvent(UpdateFinished()).post(); LoaderUpdateEvent(UpdateFinished()).post();

View file

@ -261,12 +261,12 @@ int writeAndGetPid() {
auto res = file::readString(pidFile); auto res = file::readString(pidFile);
if (!res) { if (!res) {
log::warn("Failed to read last-pid file: {}", res.error()); log::warn("Failed to read last-pid file: {}", res.unwrapErr());
} }
else { else {
auto res = numFromString<int>(res.unwrap()); auto res = numFromString<int>(res.unwrap());
if (!res) { if (!res) {
log::warn("Failed to parse last-pid file: {}", res.error()); log::warn("Failed to parse last-pid file: {}", res.unwrapErr());
} }
else lastPid = res.unwrap(); else lastPid = res.unwrap();
} }
@ -281,7 +281,7 @@ int writeAndGetPid() {
auto res = file::writeString(pidFile, std::to_string(getpid())); auto res = file::writeString(pidFile, std::to_string(getpid()));
if (!res) { if (!res) {
log::warn("Failed to write last-pid file: {}", res.error()); log::warn("Failed to write last-pid file: {}", res.unwrapErr());
} }
return lastPid; return lastPid;

View file

@ -12,7 +12,7 @@ using namespace geode::prelude;
#include <Geode/binding/AppDelegate.hpp> #include <Geode/binding/AppDelegate.hpp>
#include <Geode/loader/Log.hpp> #include <Geode/loader/Log.hpp>
#include <Geode/binding/MenuLayer.hpp> #include <Geode/binding/MenuLayer.hpp>
#include <Geode/utils/Result.hpp> #include <Geode/Result.hpp>
#include <Geode/DefaultInclude.hpp> #include <Geode/DefaultInclude.hpp>
#include <optional> #include <optional>
#include <mutex> #include <mutex>

View file

@ -41,7 +41,7 @@
#define NFD_UTF8_BOM "\xEF\xBB\xBF" #define NFD_UTF8_BOM "\xEF\xBB\xBF"
#include <stddef.h> #include <stddef.h>
#include <Geode/utils/Result.hpp> #include <Geode/Result.hpp>
#include <Geode/utils/file.hpp> #include <Geode/utils/file.hpp>
using namespace geode::prelude; using namespace geode::prelude;

View file

@ -120,7 +120,6 @@ Task<Result<std::filesystem::path>> file::pick(PickMode mode, FilePickOptions co
return RetTask::immediate(Err<std::string>("Invalid pick mode")); return RetTask::immediate(Err<std::string>("Invalid pick mode"));
} }
std::filesystem::path path; std::filesystem::path path;
Result<std::filesystem::path> result;
auto pickresult = nfdPick(nfdMode, options, &path); auto pickresult = nfdPick(nfdMode, options, &path);
if (pickresult.isErr()) { if (pickresult.isErr()) {
if (pickresult.unwrapErr() == "Dialog cancelled") { if (pickresult.unwrapErr() == "Dialog cancelled") {
@ -137,13 +136,11 @@ Task<Result<std::vector<std::filesystem::path>>> file::pickMany(FilePickOptions
std::vector<std::filesystem::path> paths; std::vector<std::filesystem::path> paths;
auto pickResult = nfdPick(NFDMode::OpenFiles, options, &paths); auto pickResult = nfdPick(NFDMode::OpenFiles, options, &paths);
Result<std::vector<std::filesystem::path>> result;
if (pickResult.isErr()) { if (pickResult.isErr()) {
result = Err(pickResult.err().value()); return RetTask::immediate(Err(pickResult.err().value()));
} else { } else {
result = Ok(paths); return RetTask::immediate(Ok(paths));
} }
return RetTask::immediate(std::move(result));
// return Task<Result<std::vector<std::filesystem::path>>>::immediate(std::move(file::pickFiles(options))); // return Task<Result<std::vector<std::filesystem::path>>>::immediate(std::move(file::pickFiles(options)));
} }

View file

@ -783,7 +783,7 @@ void server::queueBatches(
) { ) {
// we have to do the copy here, or else our values die // we have to do the copy here, or else our values die
batchedCheckUpdates(batches->back()).listen([resolve, batches, accum](auto result) { batchedCheckUpdates(batches->back()).listen([resolve, batches, accum](auto result) {
if (result->ok()) { if (result->isOk()) {
auto serverValues = result->unwrap(); auto serverValues = result->unwrap();
accum->reserve(accum->size() + serverValues.size()); accum->reserve(accum->size() + serverValues.size());
@ -798,7 +798,12 @@ void server::queueBatches(
} }
} }
else { else {
resolve(*result); if (result->isOk()) {
resolve(Ok(result->unwrap()));
}
else {
resolve(Err(result->unwrapErr()));
}
} }
}); });
} }

View file

@ -34,7 +34,7 @@ protected:
if (auto res = event->getValue()) { if (auto res = event->getValue()) {
if (res->isOk()) { if (res->isOk()) {
// Copy info first as onClose may free the listener which will free the event // Copy info first as onClose may free the listener which will free the event
auto info = **res; auto info = res->unwrap();
this->onClose(nullptr); this->onClose(nullptr);
// Run this on next frame because otherwise the popup is unable to call server::getMod for some reason // Run this on next frame because otherwise the popup is unable to call server::getMod for some reason
Loader::get()->queueInMainThread([info = std::move(info)]() mutable { Loader::get()->queueInMainThread([info = std::move(info)]() mutable {

View file

@ -14,9 +14,9 @@ LoadModSuggestionTask loadModSuggestion(LoadProblem const& problem) {
if (auto suggestionVersionRes = ComparableVersionInfo::parse(suggestionVersionStr)) { if (auto suggestionVersionRes = ComparableVersionInfo::parse(suggestionVersionStr)) {
server::ModVersion suggestionVersion = server::ModVersionLatest(); server::ModVersion suggestionVersion = server::ModVersionLatest();
if (suggestionVersionRes->getComparison() == VersionCompare::MoreEq) { if (suggestionVersionRes.unwrap().getComparison() == VersionCompare::MoreEq) {
suggestionVersion = server::ModVersionMajor { suggestionVersion = server::ModVersionMajor {
.major = suggestionVersionRes->getUnderlyingVersion().getMajor() .major = suggestionVersionRes.unwrap().getUnderlyingVersion().getMajor()
}; };
} }
// todo: if mods are allowed to specify other type of version comparisons in the future, // todo: if mods are allowed to specify other type of version comparisons in the future,
@ -195,7 +195,7 @@ server::ServerRequest<std::unordered_set<std::string>> ModSource::fetchValidTags
} }
return Ok(finalTags); return Ok(finalTags);
} }
return *result; return Ok(result->unwrap());
}, },
[](server::ServerProgress* progress) { [](server::ServerProgress* progress) {
return *progress; return *progress;

View file

@ -329,19 +329,19 @@ struct MDParser {
if (key == "scale") { if (key == "scale") {
auto scaleRes = utils::numFromString<float>(value); auto scaleRes = utils::numFromString<float>(value);
if (scaleRes) { if (scaleRes) {
spriteScale = *scaleRes; spriteScale = scaleRes.unwrap();
} }
} }
else if (key == "width") { else if (key == "width") {
auto widthRes = utils::numFromString<float>(value); auto widthRes = utils::numFromString<float>(value);
if (widthRes) { if (widthRes) {
spriteWidth = *widthRes; spriteWidth = widthRes.unwrap();
} }
} }
else if (key == "height") { else if (key == "height") {
auto heightRes = utils::numFromString<float>(value); auto heightRes = utils::numFromString<float>(value);
if (heightRes) { if (heightRes) {
spriteHeight = *heightRes; spriteHeight = heightRes.unwrap();
} }
} }
} }

View file

@ -57,7 +57,7 @@ Result<matjson::Value> utils::file::readJson(std::filesystem::path const& path)
if (!str) if (!str)
return Err(str.unwrapErr()); return Err(str.unwrapErr());
std::string error; std::string error;
auto res = matjson::parse(str.value(), error); auto res = matjson::parse(str.unwrap(), error);
if (error.size()) if (error.size())
return Err("Unable to parse JSON: " + error); return Err("Unable to parse JSON: " + error);
return Ok(res.value()); return Ok(res.value());
@ -304,7 +304,9 @@ public:
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_entry_read_open(m_handle, 0, nullptr)) mzTry(mz_zip_entry_read_open(m_handle, 0, nullptr))
.expect("Unable to open entry (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to open entry (code {})", error);
})
); );
// if the file is empty, its data is empty (duh) // if the file is empty, its data is empty (duh)
@ -323,7 +325,9 @@ public:
mz_zip_entry_close(m_handle); mz_zip_entry_close(m_handle);
GEODE_UNWRAP(file::createDirectoryAll((dir / name).parent_path())); GEODE_UNWRAP(file::createDirectoryAll((dir / name).parent_path()));
GEODE_UNWRAP(file::writeBinary(dir / name, res).expect("Unable to write to {}: {error}", dir / name)); GEODE_UNWRAP(file::writeBinary(dir / name, res).mapErr([&](auto error) {
return fmt::format("Unable to write to {}: {}", dir / name, error);
}));
return Ok(); return Ok();
} }
@ -333,14 +337,18 @@ public:
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_goto_first_entry(m_handle)) mzTry(mz_zip_goto_first_entry(m_handle))
.expect("Unable to navigate to first entry (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to navigate to first entry (code {})", error);
})
); );
uint64_t numEntries; uint64_t numEntries;
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_get_number_entry(m_handle, &numEntries)) mzTry(mz_zip_get_number_entry(m_handle, &numEntries))
.expect("Unable to get number of entries (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to get number of entries (code {})", error);
})
); );
uint32_t currentEntry = 0; uint32_t currentEntry = 0;
@ -395,7 +403,9 @@ public:
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_goto_first_entry(m_handle)) mzTry(mz_zip_goto_first_entry(m_handle))
.expect("Unable to navigate to first entry (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to navigate to first entry (code {})", error);
})
); );
GEODE_UNWRAP( GEODE_UNWRAP(
@ -403,12 +413,17 @@ public:
m_handle, m_handle,
reinterpret_cast<const char*>(name.u8string().c_str()), reinterpret_cast<const char*>(name.u8string().c_str()),
1 1
)).expect("Unable to navigate to entry (code {error})") ))
.mapErr([&](auto error) {
return fmt::format("Unable to locate entry (code {})", error);
})
); );
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_entry_read_open(m_handle, 0, nullptr)) mzTry(mz_zip_entry_read_open(m_handle, 0, nullptr))
.expect("Unable to open entry (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to open entry (code {})", error);
})
); );
// if the file is empty, its data is empty (duh) // if the file is empty, its data is empty (duh)
@ -448,7 +463,9 @@ public:
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_entry_write_open(m_handle, &info, MZ_COMPRESS_LEVEL_DEFAULT, 0, nullptr)) mzTry(mz_zip_entry_write_open(m_handle, &info, MZ_COMPRESS_LEVEL_DEFAULT, 0, nullptr))
.expect("Unable to open entry for writing (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to open entry for writing (code {})", error);
})
); );
mz_zip_entry_close(m_handle); mz_zip_entry_close(m_handle);
@ -465,7 +482,9 @@ public:
GEODE_UNWRAP( GEODE_UNWRAP(
mzTry(mz_zip_entry_write_open(m_handle, &info, MZ_COMPRESS_LEVEL_DEFAULT, 0, nullptr)) mzTry(mz_zip_entry_write_open(m_handle, &info, MZ_COMPRESS_LEVEL_DEFAULT, 0, nullptr))
.expect("Unable to open entry for writing (code {error})") .mapErr([&](auto error) {
return fmt::format("Unable to open entry for writing (code {})", error);
})
); );
auto written = mz_zip_entry_write(m_handle, data.data(), data.size()); auto written = mz_zip_entry_write(m_handle, data.data(), data.size());
if (written < 0) { if (written < 0) {
@ -550,16 +569,22 @@ bool Unzip::hasEntry(Path const& name) {
} }
Result<ByteVector> Unzip::extract(Path const& name) { Result<ByteVector> Unzip::extract(Path const& name) {
return m_impl->extract(name).expect("{error} (entry {})", name.string()); return m_impl->extract(name).mapErr([&](auto error) {
return fmt::format("Unable to extract entry {}: {}", name.string(), error);
});
} }
Result<> Unzip::extractTo(Path const& name, Path const& path) { Result<> Unzip::extractTo(Path const& name, Path const& path) {
GEODE_UNWRAP_INTO(auto bytes, m_impl->extract(name).expect("{error} (entry {})", name.string())); GEODE_UNWRAP_INTO(auto bytes, m_impl->extract(name).mapErr([&](auto error) {
return fmt::format("Unable to extract entry {}: {}", name.string(), error);
}));
// create containing directories for target path // create containing directories for target path
if (path.has_parent_path()) { if (path.has_parent_path()) {
GEODE_UNWRAP(file::createDirectoryAll(path.parent_path())); GEODE_UNWRAP(file::createDirectoryAll(path.parent_path()));
} }
GEODE_UNWRAP(file::writeBinary(path, bytes).expect("Unable to write file {}: {error}", path.string())); GEODE_UNWRAP(file::writeBinary(path, bytes).mapErr([&](auto error) {
return fmt::format("Unable to write file {}: {}", path.string(), error);
}));
return Ok(); return Ok();
} }

View file

@ -1,4 +1,4 @@
#include <Geode/utils/Result.hpp> #include <Geode/Result.hpp>
#include <Geode/utils/general.hpp> #include <Geode/utils/general.hpp>
#include <filesystem> #include <filesystem>
#include <fmt/core.h> #include <fmt/core.h>
@ -498,7 +498,7 @@ WebRequest& WebRequest::header(std::string_view name, std::string_view value) {
int timeoutValue = 5; int timeoutValue = 5;
auto res = numFromString<int>(value.substr(numStart, numLength)); auto res = numFromString<int>(value.substr(numStart, numLength));
if (res) { if (res) {
timeoutValue = res.value(); timeoutValue = res.unwrap();
} }
timeout(std::chrono::seconds(timeoutValue)); timeout(std::chrono::seconds(timeoutValue));