Rework handling of esplugin errors

The error scenario represented by PluginNotLoadedError is distinguished from all other esplugin errors by LOOT, so it's worth handling separately.
This commit is contained in:
Oliver Hamlet
2025-06-08 20:26:07 +01:00
parent 05c984c769
commit 11bd321861
20 changed files with 81 additions and 321 deletions
@@ -1,46 +0,0 @@
/* LOOT
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
Fallout: New Vegas.
Copyright (C) 2012-2016 WrinklyNinja
This file is part of LOOT.
LOOT is free software: you can redistribute
it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
LOOT is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with LOOT. If not, see
<https://www.gnu.org/licenses/>.
*/
#include "loot/exception/error_categories.h"
#include <string>
namespace loot {
namespace detail {
class esplugin_category : public std::error_category {
const char* name() const noexcept override { return "esplugin"; }
std::string message(int) const override { return "esplugin error"; }
bool equivalent(const std::error_code& code, int) const noexcept override {
return code.category().name() == name();
}
};
}
LOOT_API const std::error_category& esplugin_category() {
static detail::esplugin_category instance;
return instance;
}
}
+6 -21
View File
@@ -3,7 +3,7 @@
#include <charconv>
#include "loot/exception/cyclic_interaction_error.h"
#include "loot/exception/error_categories.h"
#include "loot/exception/plugin_not_loaded_error.h"
#include "loot/exception/undefined_group_error.h"
#include "loot/vertex.h"
@@ -15,7 +15,8 @@ using loot::Vertex;
constexpr std::string_view CYCLIC_ERROR_PREFIX = "CyclicInteractionError: "sv;
constexpr std::string_view UNDEFINED_GROUP_ERROR_PREFIX =
"UndefinedGroupError: "sv;
constexpr std::string_view ESPLUGIN_ERROR_PREFIX = "EspluginError: "sv;
constexpr std::string_view PLUGIN_NOT_LOADED_ERROR_PREFIX =
"PluginNotLoadedError: "sv;
constexpr std::string_view INVALID_ARGUMENT_PREFIX = "InvalidArgument: "sv;
bool startsWith(std::string_view str, std::string_view prefix) {
@@ -112,20 +113,6 @@ std::string getErrorSuffix(std::string_view what) {
return std::string(what.substr(sepPos + 2));
}
std::pair<int, std::string> parseSystemError(std::string_view whatSuffix) {
const auto sepPos = whatSuffix.find(": ");
int code;
const auto result =
std::from_chars(whatSuffix.data(), whatSuffix.data() + sepPos, code);
if (result.ec != std::errc{}) {
std::string err = "Could not parse error code from string: ";
err += whatSuffix;
throw std::runtime_error(err);
}
return std::make_pair(code, std::string(whatSuffix.substr(sepPos + 2)));
}
}
namespace loot {
@@ -136,12 +123,10 @@ std::exception_ptr mapError(const ::rust::Error& error) {
} else if (startsWith(error.what(), UNDEFINED_GROUP_ERROR_PREFIX)) {
return std::make_exception_ptr(
UndefinedGroupError(getErrorSuffix(error.what())));
} else if (startsWith(error.what(), ESPLUGIN_ERROR_PREFIX)) {
const auto [code, details] = parseSystemError(
std::string_view(error.what()).substr(ESPLUGIN_ERROR_PREFIX.size()));
} else if (startsWith(error.what(), PLUGIN_NOT_LOADED_ERROR_PREFIX)) {
return std::make_exception_ptr(
std::system_error(code, esplugin_category(), details));
PluginNotLoadedError("The plugin \"" + getErrorSuffix(error.what()) +
"\" has not been loaded"));
} else if (startsWith(error.what(), INVALID_ARGUMENT_PREFIX)) {
return std::make_exception_ptr(
std::invalid_argument(getErrorSuffix(error.what())));