Use Rust Filename comparisons for C++ Filename operators

To prevent inconsistencies between implementations. This means allocating new boxed Filenames for each comparison, but an extra string copy is avoided by making the C++ operators friends of the C++ class (which is ABI-safe).
This commit is contained in:
Oliver Hamlet
2025-05-05 11:45:50 +01:00
parent eabc7a5d85
commit 1317eea055
6 changed files with 21 additions and 16 deletions
-1
View File
@@ -9,7 +9,6 @@ cxx = { version = "1.0", features = ["c++17"] }
delegate = "0.13.2"
libloot = { path = ".." }
libloot-ffi-errors = { path = "../ffi-errors" }
unicase = "2.8.1"
[build-dependencies]
cxx-build = "1.0"
+4
View File
@@ -54,6 +54,10 @@ public:
private:
std::string filename_;
LOOT_API friend bool operator==(const Filename& lhs, const Filename& rhs);
LOOT_API friend bool operator<(const Filename& lhs, const Filename& rhs);
};
/**
+4 -2
View File
@@ -35,7 +35,8 @@ Filename::Filename(std::string_view filename) : filename_(filename) {}
Filename::operator std::string() const { return filename_; }
bool operator==(const Filename& lhs, const Filename& rhs) {
return loot::rust::compare_filenames(std::string(lhs), std::string(rhs)) == 0;
return loot::rust::new_filename(lhs.filename_)
->eq(*loot::rust::new_filename(rhs.filename_));
}
bool operator!=(const Filename& lhs, const Filename& rhs) {
@@ -43,7 +44,8 @@ bool operator!=(const Filename& lhs, const Filename& rhs) {
}
bool operator<(const Filename& lhs, const Filename& rhs) {
return loot::rust::compare_filenames(std::string(lhs), std::string(rhs)) < 0;
return loot::rust::new_filename(lhs.filename_)
->lt(*loot::rust::new_filename(rhs.filename_));
}
bool operator>(const Filename& lhs, const Filename& rhs) { return rhs < lhs; }
+12 -11
View File
@@ -119,7 +119,6 @@ use std::{
ffi::{CString, c_char, c_uchar, c_uint, c_void},
sync::{Mutex, atomic::AtomicPtr},
};
use unicase::UniCase;
use libloot::set_logging_callback;
pub use libloot::{is_compatible, libloot_revision, libloot_version};
@@ -181,14 +180,6 @@ pub type OptionalPluginMetadata = Optional<PluginMetadata>;
pub type OptionalCrc = Optional<u32>;
fn compare_filenames(lhs: &str, rhs: &str) -> i8 {
match UniCase::new(lhs).cmp(&UniCase::new(rhs)) {
std::cmp::Ordering::Less => -1,
std::cmp::Ordering::Equal => 0,
std::cmp::Ordering::Greater => 1,
}
}
fn set_log_level(level: ffi::LogLevel) -> Result<(), VerboseError> {
libloot::set_log_level(level.try_into()?);
Ok(())
@@ -295,8 +286,6 @@ mod ffi {
contents: &[MessageContent],
language: &str,
) -> OptionalMessageContentRef;
fn compare_filenames(lhs: &str, rhs: &str) -> i8;
}
extern "Rust" {
@@ -633,6 +622,18 @@ mod ffi {
pub fn as_str(&self) -> &str;
pub fn boxed_clone(&self) -> Box<Filename>;
pub fn eq(&self, other: &Filename) -> bool;
pub fn ne(&self, other: &Filename) -> bool;
pub fn lt(&self, other: &Filename) -> bool;
pub fn le(&self, other: &Filename) -> bool;
pub fn gt(&self, other: &Filename) -> bool;
pub fn ge(&self, other: &Filename) -> bool;
}
extern "Rust" {
+1 -1
View File
@@ -446,7 +446,7 @@ impl From<Box<File>> for libloot::metadata::File {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Filename(libloot::metadata::Filename);