Deny various rustc and clippy lints in ffi-errors crate

This commit is contained in:
Oliver Hamlet
2025-04-23 00:16:09 +01:00
parent e0d890ab1a
commit 3926e75792
5 changed files with 199 additions and 61 deletions
+1
View File
@@ -47,6 +47,7 @@ impl std::fmt::Display for VerboseError {
SystemErrorCategory::Esplugin => "EspluginError",
SystemErrorCategory::Libloadorder => "LibloadorderError",
SystemErrorCategory::LootConditionInterpreter => "LciError",
_ => "UnknownCategoryError",
};
write!(f, "{}: {}: {}", prefix, e.code(), e.message())
}
+11 -4
View File
@@ -44,6 +44,13 @@ pub static ESP_ERROR_UNRESOLVED_RECORD_IDS: c_int = 13;
#[unsafe(no_mangle)]
pub static ESP_ERROR_PLUGIN_METADATA_NOT_FOUND: c_int = 14;
#[unsafe(no_mangle)]
pub static ESP_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() {
std::io::ErrorKind::NotFound => ESP_ERROR_FILE_NOT_FOUND,
@@ -52,12 +59,12 @@ fn map_io_error(err: &std::io::Error) -> c_int {
}
}
#[must_use]
pub fn map_error(err: &Error) -> c_int {
match *err {
Error::IoError(ref x) => map_io_error(x),
match err {
Error::IoError(x) => map_io_error(x),
Error::NoFilename(_) => ESP_ERROR_NO_FILENAME,
Error::ParsingIncomplete(_) => ESP_ERROR_PARSE_ERROR,
Error::ParsingError(_, _) => ESP_ERROR_PARSE_ERROR,
Error::ParsingIncomplete(_) | Error::ParsingError(_, _) => ESP_ERROR_PARSE_ERROR,
Error::DecodeError(_) => ESP_ERROR_TEXT_DECODE_ERROR,
Error::UnresolvedRecordIds(_) => ESP_ERROR_UNRESOLVED_RECORD_IDS,
Error::PluginMetadataNotFound(_) => ESP_ERROR_PLUGIN_METADATA_NOT_FOUND,
+7 -3
View File
@@ -33,11 +33,15 @@ pub static LCI_ERROR_TEXT_ENCODE_FAIL: c_int = -7;
#[unsafe(no_mangle)]
pub static LCI_ERROR_INTERNAL_LOGIC_ERROR: c_int = -8;
#[unsafe(no_mangle)]
pub static LCI_ERROR_UNKNOWN: c_int = c_int::MAX;
#[must_use]
pub fn map_error(err: &Error) -> c_int {
match err {
Error::ParsingIncomplete(_) => LCI_ERROR_PARSING_ERROR,
Error::UnconsumedInput(_) => LCI_ERROR_PARSING_ERROR,
Error::ParsingError(_, _) => LCI_ERROR_PARSING_ERROR,
Error::ParsingIncomplete(_) | Error::UnconsumedInput(_) | Error::ParsingError(_, _) => {
LCI_ERROR_PARSING_ERROR
}
Error::PeParsingError(_, _) => LCI_ERROR_PE_PARSING_ERROR,
Error::IoError(_, _) => LCI_ERROR_IO_ERROR,
_ => LCI_ERROR_INTERNAL_LOGIC_ERROR,
+143 -23
View File
@@ -1,8 +1,106 @@
// Deny some rustc lints that are allow-by-default.
#![deny(
ambiguous_negative_literals,
impl_trait_overcaptures,
let_underscore_drop,
missing_copy_implementations,
missing_debug_implementations,
non_ascii_idents,
redundant_imports,
redundant_lifetimes,
trivial_casts,
trivial_numeric_casts,
unit_bindings,
unreachable_pub
)]
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
// Selectively deny clippy restriction lints.
#![deny(
clippy::allow_attributes,
clippy::as_conversions,
clippy::as_underscore,
clippy::assertions_on_result_states,
clippy::big_endian_bytes,
clippy::cfg_not_test,
clippy::clone_on_ref_ptr,
clippy::create_dir,
clippy::dbg_macro,
clippy::decimal_literal_representation,
clippy::default_numeric_fallback,
clippy::doc_include_without_cfg,
clippy::empty_drop,
clippy::error_impl_error,
clippy::exit,
clippy::exhaustive_enums,
clippy::expect_used,
clippy::filetype_is_file,
clippy::float_cmp_const,
clippy::fn_to_numeric_cast_any,
clippy::get_unwrap,
clippy::host_endian_bytes,
clippy::if_then_some_else_none,
clippy::indexing_slicing,
clippy::infinite_loop,
clippy::integer_division,
clippy::integer_division_remainder_used,
clippy::iter_over_hash_type,
clippy::let_underscore_must_use,
clippy::lossy_float_literal,
clippy::map_err_ignore,
clippy::map_with_unused_argument_over_ranges,
clippy::mem_forget,
clippy::missing_assert_message,
clippy::missing_asserts_for_indexing,
clippy::missing_asserts_for_indexing,
clippy::mixed_read_write_in_expression,
clippy::multiple_inherent_impl,
clippy::multiple_unsafe_ops_per_block,
clippy::mutex_atomic,
clippy::mutex_integer,
clippy::needless_raw_strings,
clippy::non_ascii_literal,
clippy::non_zero_suggestions,
clippy::panic,
clippy::panic_in_result_fn,
clippy::partial_pub_fields,
clippy::pathbuf_init_then_push,
clippy::precedence_bits,
clippy::print_stderr,
clippy::print_stdout,
clippy::rc_buffer,
clippy::rc_mutex,
clippy::redundant_type_annotations,
clippy::ref_patterns,
clippy::rest_pat_in_fully_bound_structs,
clippy::str_to_string,
clippy::string_lit_chars_any,
clippy::string_slice,
clippy::string_to_string,
clippy::suspicious_xor_used_as_pow,
clippy::tests_outside_test_module,
clippy::todo,
clippy::try_err,
clippy::undocumented_unsafe_blocks,
clippy::unimplemented,
clippy::unnecessary_safety_comment,
clippy::unneeded_field_pattern,
clippy::unreachable,
clippy::unused_result_ok,
clippy::unwrap_in_result,
clippy::unwrap_used,
clippy::use_debug,
clippy::verbose_file_reads,
clippy::wildcard_enum_match_arm
)]
use std::{
error::Error,
ffi::{c_int, c_uchar},
};
use esplugin::ESP_ERROR_UNKNOWN;
use lci::LCI_ERROR_UNKNOWN;
use libloadorder::LIBLO_ERROR_UNKNOWN;
use libloot::error::{ConditionEvaluationError, LoadOrderError, PluginDataError};
pub mod esplugin;
@@ -23,6 +121,7 @@ pub static LIBLOOT_SYSTEM_ERROR_CATEGORY_LCI: c_uchar = 3;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(u8)]
#[non_exhaustive]
pub enum SystemErrorCategory {
Esplugin = LIBLOOT_SYSTEM_ERROR_CATEGORY_ESPLUGIN,
Libloadorder = LIBLOOT_SYSTEM_ERROR_CATEGORY_LIBLOADORDER,
@@ -49,14 +148,17 @@ pub struct SystemError {
}
impl SystemError {
#[must_use]
pub fn code(&self) -> c_int {
self.code
}
#[must_use]
pub fn category(&self) -> SystemErrorCategory {
self.category
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
@@ -76,48 +178,66 @@ impl std::error::Error for SystemError {}
impl From<PluginDataError> for SystemError {
fn from(value: PluginDataError) -> Self {
let error = value
let (code, message) = if let Some(error) = value
.source()
.expect("LoadOrderError has source")
.downcast_ref::<::esplugin::Error>()
.expect("LoadOrderError source is an esplugin::Error");
let error_code = crate::esplugin::map_error(error);
.and_then(|s| s.downcast_ref::<::esplugin::Error>())
{
let error_code = crate::esplugin::map_error(error);
(error_code, error.to_string())
} else {
(
ESP_ERROR_UNKNOWN,
"Could not retrieve esplugin error message".to_owned(),
)
};
SystemError {
code: error_code,
code,
category: SystemErrorCategory::Esplugin,
message: error.to_string(),
message,
}
}
}
impl From<LoadOrderError> for SystemError {
fn from(value: LoadOrderError) -> Self {
let error = value
let (code, message) = if let Some(error) = value
.source()
.expect("LoadOrderError has source")
.downcast_ref::<loadorder::Error>()
.expect("LoadOrderError source is a loadorder::Error");
let error_code = crate::libloadorder::map_error(error);
.and_then(|s| s.downcast_ref::<::loadorder::Error>())
{
let error_code = crate::libloadorder::map_error(error);
(error_code, error.to_string())
} else {
(
LIBLO_ERROR_UNKNOWN,
"Could not retrieve libloadorder error message".to_owned(),
)
};
SystemError {
code: error_code,
code,
category: SystemErrorCategory::Libloadorder,
message: error.to_string(),
message,
}
}
}
impl From<ConditionEvaluationError> for SystemError {
fn from(value: ConditionEvaluationError) -> Self {
let error = value
let (code, message) = if let Some(error) = value
.source()
.expect("ConditionEvaluationError has source")
.downcast_ref::<loot_condition_interpreter::Error>()
.expect("ConditionEvaluationError source is a loot_condition_interpreter::Error");
let error_code = crate::lci::map_error(error);
.and_then(|s| s.downcast_ref::<::loot_condition_interpreter::Error>())
{
let error_code = crate::lci::map_error(error);
(error_code, error.to_string())
} else {
(
LCI_ERROR_UNKNOWN,
"Could not retrieve loot-condition-interpreter error message".to_owned(),
)
};
SystemError {
code: error_code,
code,
category: SystemErrorCategory::LootConditionInterpreter,
message: error.to_string(),
message,
}
}
}
@@ -137,9 +257,9 @@ pub fn fmt_error_chain(
mut error: &dyn std::error::Error,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(f, "{}", error)?;
write!(f, "{error}")?;
while let Some(source) = error.source() {
write!(f, ": {}", source)?;
write!(f, ": {source}")?;
error = source;
}
Ok(())
+37 -31
View File
@@ -1,5 +1,5 @@
use loadorder::Error;
use std::ffi::c_int;
use std::{ffi::c_int, io::ErrorKind};
/// There is a mismatch between the files used to keep track of load order.
///
@@ -70,49 +70,55 @@ pub static LIBLO_ERROR_SYSTEM_ERROR: c_int = 22;
#[unsafe(no_mangle)]
pub static LIBLO_ERROR_NO_PATH: c_int = 23;
/// Matches the value of the highest-numbered return code.
/// Matches the value of the highest-numbered return code, aside from `LIBLO_ERROR_UNKNOWN`.
///
/// Provided in case clients wish to incorporate additional return codes in their implementation
/// and desire some method of avoiding value conflicts.
#[unsafe(no_mangle)]
pub static LIBLO_RETURN_MAX: c_int = 23;
#[unsafe(no_mangle)]
pub static 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 {
use std::io::ErrorKind::*;
match err.kind() {
NotFound => LIBLO_ERROR_FILE_NOT_FOUND,
AlreadyExists => LIBLO_ERROR_FILE_RENAME_FAIL,
PermissionDenied => LIBLO_ERROR_IO_PERMISSION_DENIED,
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 fn map_error(err: &Error) -> c_int {
use Error::*;
match *err {
InvalidPath(_) => LIBLO_ERROR_FILE_NOT_FOUND,
IoError(_, ref x) => map_io_error(x),
NoFilename(_) => LIBLO_ERROR_FILE_PARSE_FAIL,
DecodeError(_) => LIBLO_ERROR_TEXT_DECODE_FAIL,
EncodeError(_) => LIBLO_ERROR_TEXT_ENCODE_FAIL,
PluginParsingError(_, _) => LIBLO_ERROR_FILE_PARSE_FAIL,
PluginNotFound(_) => LIBLO_ERROR_INVALID_ARGS,
TooManyActivePlugins { .. } => LIBLO_ERROR_INVALID_ARGS,
DuplicatePlugin(_) => LIBLO_ERROR_INVALID_ARGS,
NonMasterBeforeMaster { .. } => LIBLO_ERROR_INVALID_ARGS,
InvalidEarlyLoadingPluginPosition { .. } => LIBLO_ERROR_INVALID_ARGS,
ImplicitlyActivePlugin(_) => LIBLO_ERROR_INVALID_ARGS,
NoLocalAppData => LIBLO_ERROR_INVALID_ARGS,
NoDocumentsPath => LIBLO_ERROR_INVALID_ARGS,
NoUserConfigPath => LIBLO_ERROR_NO_PATH,
NoUserDataPath => LIBLO_ERROR_NO_PATH,
NoProgramFilesPath => LIBLO_ERROR_NO_PATH,
UnrepresentedHoist { .. } => LIBLO_ERROR_INVALID_ARGS,
InstalledPlugin(_) => LIBLO_ERROR_INVALID_ARGS,
IniParsingError { .. } => LIBLO_ERROR_FILE_PARSE_FAIL,
VdfParsingError(_, _) => LIBLO_ERROR_FILE_PARSE_FAIL,
SystemError(_, _) => LIBLO_ERROR_SYSTEM_ERROR,
InvalidBlueprintPluginPosition { .. } => LIBLO_ERROR_INVALID_ARGS,
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,
}
}