diff --git a/Cargo.lock b/Cargo.lock index 6453344b..a22f1f69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -579,7 +579,6 @@ name = "libloot-ffi-errors" version = "0.26.3" dependencies = [ "esplugin", - "libloadorder", "libloot", ] diff --git a/Cargo.toml b/Cargo.toml index fefd6545..10827294 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later" [dependencies] crc32fast = "1.4.2" fancy-regex = "0.14.0" +libloadorder = "18.4.0" log = { version = "0.4.26", features = ["std"] } loot-condition-interpreter = "5.3.2" petgraph = "0.8.1" @@ -16,7 +17,6 @@ saphyr = "0.0.4" unicase = "2.8.1" esplugin.workspace = true -libloadorder.workspace = true [target.'cfg(windows)'.dependencies] windows = { version = "0.61.1", features = ["Win32_Storage_FileSystem"] } @@ -30,7 +30,6 @@ members = ["cpp", "ffi-errors", "nodejs", "parameterized-test", "python"] [workspace.dependencies] esplugin = "6.1.3" -libloadorder = "18.4.0" [profile.release] debug = "limited" diff --git a/cpp/docs/api/reference.rst b/cpp/docs/api/reference.rst index e12f4f53..fa110b1d 100644 --- a/cpp/docs/api/reference.rst +++ b/cpp/docs/api/reference.rst @@ -105,5 +105,3 @@ LOOT uses error category objects to identify errors with codes that originate in lower-level libraries. .. doxygenfunction:: loot::esplugin_category - -.. doxygenfunction:: loot::libloadorder_category diff --git a/cpp/include/loot/exception/error_categories.h b/cpp/include/loot/exception/error_categories.h index 42773fcc..d5c005c8 100644 --- a/cpp/include/loot/exception/error_categories.h +++ b/cpp/include/loot/exception/error_categories.h @@ -37,14 +37,6 @@ namespace loot { * derived from std::error_category. */ LOOT_API const std::error_category& esplugin_category(); - -/** - * @brief Get the error category that can be used to identify system_error - * exceptions that are due to libloadorder errors. - * @returns A reference to the static object of unspecified runtime type, - * derived from std::error_category. - */ -LOOT_API const std::error_category& libloadorder_category(); } #endif diff --git a/cpp/src/api/exception/error_categories.cpp b/cpp/src/api/exception/error_categories.cpp index b4bd9521..c6035f07 100644 --- a/cpp/src/api/exception/error_categories.cpp +++ b/cpp/src/api/exception/error_categories.cpp @@ -37,25 +37,10 @@ class esplugin_category : public std::error_category { return code.category().name() == name(); } }; - -class libloadorder_category : public std::error_category { - const char* name() const noexcept override { return "libloadorder"; } - - std::string message(int) const override { return "Libloadorder 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; } - -LOOT_API const std::error_category& libloadorder_category() { - static detail::libloadorder_category instance; - return instance; -} } diff --git a/cpp/src/api/exception/exception.cpp b/cpp/src/api/exception/exception.cpp index 25375af6..3bbb7e75 100644 --- a/cpp/src/api/exception/exception.cpp +++ b/cpp/src/api/exception/exception.cpp @@ -16,7 +16,6 @@ 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 LIBLOADORDER_ERROR_PREFIX = "LibloadorderError: "sv; constexpr std::string_view INVALID_ARGUMENT_PREFIX = "InvalidArgument: "sv; bool startsWith(std::string_view str, std::string_view prefix) { @@ -143,14 +142,6 @@ std::exception_ptr mapError(const ::rust::Error& error) { return std::make_exception_ptr( std::system_error(code, esplugin_category(), details)); - - } else if (startsWith(error.what(), LIBLOADORDER_ERROR_PREFIX)) { - const auto [code, details] = - parseSystemError(std::string_view(error.what()) - .substr(LIBLOADORDER_ERROR_PREFIX.size())); - - return std::make_exception_ptr( - std::system_error(code, libloadorder_category(), details)); } else if (startsWith(error.what(), INVALID_ARGUMENT_PREFIX)) { return std::make_exception_ptr( std::invalid_argument(getErrorSuffix(error.what()))); diff --git a/cpp/src/error.rs b/cpp/src/error.rs index 1c27e63d..d52c1f85 100644 --- a/cpp/src/error.rs +++ b/cpp/src/error.rs @@ -44,7 +44,6 @@ impl std::fmt::Display for VerboseError { Self::SystemError(e) => { let prefix = match e.category() { SystemErrorCategory::Esplugin => "EspluginError", - SystemErrorCategory::Libloadorder => "LibloadorderError", _ => "UnknownCategoryError", }; write!(f, "{}: {}: {}", prefix, e.code(), e.message()) @@ -64,13 +63,14 @@ variant_box_from_error!(LoadMetadataError, VerboseError::Other); variant_box_from_error!(WriteMetadataError, VerboseError::Other); variant_box_from_error!(ConditionEvaluationError, VerboseError::Other); variant_box_from_error!(MetadataRetrievalError, VerboseError::Other); +variant_box_from_error!(LoadOrderError, VerboseError::Other); +variant_box_from_error!(LoadOrderStateError, VerboseError::Other); impl From for VerboseError { fn from(value: GameHandleCreationError) -> Self { match value { - GameHandleCreationError::LoadOrderError(e) => e.into(), GameHandleCreationError::NotADirectory(_) => Self::InvalidArgument(value.to_string()), - _ => Self::Other(Box::new(value)), + GameHandleCreationError::LoadOrderError(_) | _ => Self::Other(Box::new(value)), } } } @@ -102,21 +102,6 @@ impl From for VerboseError { } } -impl From for VerboseError { - fn from(value: LoadOrderStateError) -> Self { - match value { - LoadOrderStateError::LoadOrderError(e) => e.into(), - LoadOrderStateError::DatabaseLockPoisoned | _ => Self::Other(Box::new(value)), - } - } -} - -impl From for VerboseError { - fn from(value: LoadOrderError) -> Self { - Self::SystemError(SystemError::from(value)) - } -} - impl From for VerboseError { fn from(value: GroupsPathError) -> Self { match value { diff --git a/cpp/src/tests/api/interface/create_game_handle_test.h b/cpp/src/tests/api/interface/create_game_handle_test.h index 80539b9b..c92dd4dc 100644 --- a/cpp/src/tests/api/interface/create_game_handle_test.h +++ b/cpp/src/tests/api/interface/create_game_handle_test.h @@ -150,7 +150,7 @@ TEST_P( GetParam() == GameType::oblivionRemastered) { EXPECT_NO_THROW(CreateGameHandle(GetParam(), gamePath)); } else { - EXPECT_THROW(CreateGameHandle(GetParam(), gamePath), std::system_error); + EXPECT_THROW(CreateGameHandle(GetParam(), gamePath), std::runtime_error); } } #else diff --git a/ffi-errors/Cargo.toml b/ffi-errors/Cargo.toml index 042ce582..af1b3a93 100644 --- a/ffi-errors/Cargo.toml +++ b/ffi-errors/Cargo.toml @@ -8,4 +8,3 @@ license = "GPL-3.0-or-later" libloot = { path = ".." } esplugin.workspace = true -libloadorder.workspace = true diff --git a/ffi-errors/src/lib.rs b/ffi-errors/src/lib.rs index 52c7de3e..13e9567b 100644 --- a/ffi-errors/src/lib.rs +++ b/ffi-errors/src/lib.rs @@ -94,10 +94,9 @@ )] use std::{error::Error, ffi::c_int}; -use libloot::error::{LoadOrderError, PluginDataError}; +use libloot::error::PluginDataError; mod esplugin; -mod libloadorder; // It's important for API stability that these variants' values don't change. #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -105,14 +104,12 @@ mod libloadorder; #[non_exhaustive] pub enum SystemErrorCategory { Esplugin = 1, - Libloadorder = 2, } impl std::fmt::Display for SystemErrorCategory { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { SystemErrorCategory::Esplugin => write!(f, "esplugin"), - SystemErrorCategory::Libloadorder => write!(f, "libloadorder"), } } } @@ -169,22 +166,6 @@ impl From for SystemError { } } -impl From for SystemError { - fn from(value: LoadOrderError) -> Self { - const LIBLOADORDER_ERROR_UNKNOWN: (i32, &str) = ( - libloadorder::LIBLO_ERROR_UNKNOWN, - "Could not retrieve libloadorder error message", - ); - - from_error( - value, - SystemErrorCategory::Libloadorder, - LIBLOADORDER_ERROR_UNKNOWN, - crate::libloadorder::map_error, - ) - } -} - fn from_error c_int>( error: U, category: SystemErrorCategory, diff --git a/ffi-errors/src/libloadorder.rs b/ffi-errors/src/libloadorder.rs deleted file mode 100644 index 57a314b8..00000000 --- a/ffi-errors/src/libloadorder.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Unless otherwise noted, these constants and the mapping logic are copied from -// libloadorder-ffi. - -use loadorder::Error; -use std::{ffi::c_int, io::ErrorKind}; - -/// The specified file could not be found. -const LIBLO_ERROR_FILE_NOT_FOUND: c_int = 6; - -/// A file could not be renamed. -const LIBLO_ERROR_FILE_RENAME_FAIL: c_int = 7; - -/// There was an error parsing a plugin file. -const LIBLO_ERROR_FILE_PARSE_FAIL: c_int = 10; - -/// Invalid arguments were given for the function. -const LIBLO_ERROR_INVALID_ARGS: c_int = 12; - -/// An unknown I/O error occurred. This is used when the I/O error kind doesn't -/// fit another error code. -const LIBLO_ERROR_IO_ERROR: c_int = 15; - -/// Permission denied while trying to access a filesystem path. -const LIBLO_ERROR_IO_PERMISSION_DENIED: c_int = 16; - -/// A plugin filename contains characters that do not have Windows-1252 code -/// points, or a character string contains a null character. -const LIBLO_ERROR_TEXT_ENCODE_FAIL: c_int = 17; - -/// Text expected to be encoded in Windows-1252 could not be decoded to UTF-8. -const LIBLO_ERROR_TEXT_DECODE_FAIL: c_int = 18; - -/// The library encountered an error that should not have been possible to -/// encounter. -const LIBLO_ERROR_INTERNAL_LOGIC_ERROR: c_int = 19; - -/// An unknown operating system error occurred. -const LIBLO_ERROR_SYSTEM_ERROR: c_int = 22; - -/// A system path definition (e.g. for local app data on Windows, or $HOME on -/// Linux) could not be found. -const LIBLO_ERROR_NO_PATH: c_int = 23; - -// This constant is not copied from libloadorder-ffi, but does not conflict with -// any values defined there. -pub(crate) const LIBLO_ERROR_UNKNOWN: c_int = c_int::MAX; - -#[expect( - clippy::wildcard_enum_match_arm, - reason = "It doesn't matter if other I/O error kinds are added in the future" -)] -fn map_io_error(err: &std::io::Error) -> c_int { - match err.kind() { - ErrorKind::NotFound => LIBLO_ERROR_FILE_NOT_FOUND, - ErrorKind::AlreadyExists => LIBLO_ERROR_FILE_RENAME_FAIL, - ErrorKind::PermissionDenied => LIBLO_ERROR_IO_PERMISSION_DENIED, - _ => LIBLO_ERROR_IO_ERROR, - } -} - -#[must_use] -pub(crate) fn map_error(err: &Error) -> c_int { - match err { - Error::InvalidPath(_) => LIBLO_ERROR_FILE_NOT_FOUND, - Error::IoError(_, x) => map_io_error(x), - Error::NoFilename(_) - | Error::PluginParsingError(_, _) - | Error::IniParsingError { .. } - | Error::VdfParsingError(_, _) => LIBLO_ERROR_FILE_PARSE_FAIL, - Error::DecodeError(_) => LIBLO_ERROR_TEXT_DECODE_FAIL, - Error::EncodeError(_) => LIBLO_ERROR_TEXT_ENCODE_FAIL, - Error::PluginNotFound(_) - | Error::TooManyActivePlugins { .. } - | Error::DuplicatePlugin(_) - | Error::NonMasterBeforeMaster { .. } - | Error::InvalidEarlyLoadingPluginPosition { .. } - | Error::ImplicitlyActivePlugin(_) - | Error::NoLocalAppData - | Error::NoDocumentsPath - | Error::UnrepresentedHoist { .. } - | Error::InstalledPlugin(_) - | Error::InvalidBlueprintPluginPosition { .. } => LIBLO_ERROR_INVALID_ARGS, - Error::NoUserConfigPath | Error::NoUserDataPath | Error::NoProgramFilesPath => { - LIBLO_ERROR_NO_PATH - } - Error::SystemError(_, _) => LIBLO_ERROR_SYSTEM_ERROR, - _ => LIBLO_ERROR_INTERNAL_LOGIC_ERROR, - } -} diff --git a/python/README.md b/python/README.md index b64f1bf3..f939c807 100644 --- a/python/README.md +++ b/python/README.md @@ -47,5 +47,4 @@ python - The Python exceptions that errors are mapped to are not the same as in the Rust or C++ interfaces: - The API provides the custom `CyclicInteractionError`, `UndefinedGroupError`, `EspluginError` exception types. - All other errors are raised as `ValueError` exceptions. - - There's no equivalent to the C++ interface's libloadorder system error category. - The `LogLevel` enum and `set_logging_callback()` and `set_log_level()` functions are not exposed because the logging is integrated with Python's `logging` module instead.