summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDennis van der Schagt <dennisschagt@gmail.com>2024-01-06 00:08:04 +0100
committerDennis van der Schagt <dennisschagt@gmail.com>2024-04-05 01:04:31 +0200
commit4b8034ce285fe9d2cf5dd80b8c0b0ed9a992223a (patch)
treef9a282d51b4df35587d695fb280c8b2a30153f34
parent73db155c883bbbdc4813f411e4aeecdf6f8f5456 (diff)
Move utils bridged methods into their own ffi module
Discovered that we can use `Pin<&mut ...>` to allow mutation of Rust types defined in another cxx bridge module, based on: - https://cxx.rs/extern-c++.html#opaque-c-types > Unlike extern Rust types and shared types, an extern C++ type is not > permitted to be passed by plain mutable reference &mut MyType across the > FFI bridge. For mutation support, the bridge is required to use Pin<&mut > MyType>. This is to safeguard against things like mem::swap-ing the > contents of two mutable references, given that Rust doesn't have > information about the size of the underlying object and couldn't invoke > an appropriate C++ move constructor anyway. - https://github.com/dtolnay/cxx/issues/942
-rw-r--r--include/filepath.h2
-rw-r--r--rust/libnewsboat-ffi/src/filepath.rs27
-rw-r--r--rust/libnewsboat-ffi/src/utils.rs21
-rw-r--r--src/utils.cpp24
4 files changed, 34 insertions, 40 deletions
diff --git a/include/filepath.h b/include/filepath.h
index 1fc9e2d0..90c2d905 100644
--- a/include/filepath.h
+++ b/include/filepath.h
@@ -36,7 +36,7 @@ public:
{
}
- Filepath(rust::Box<filepath::bridged::PathBuf> rs_object)
+ Filepath(rust::Box<filepath::bridged::PathBuf>&& rs_object)
: rs_object(std::move(rs_object))
{
}
diff --git a/rust/libnewsboat-ffi/src/filepath.rs b/rust/libnewsboat-ffi/src/filepath.rs
index d960ff3b..778ed0de 100644
--- a/rust/libnewsboat-ffi/src/filepath.rs
+++ b/rust/libnewsboat-ffi/src/filepath.rs
@@ -27,13 +27,6 @@ mod bridged {
fn set_extension(filepath: &mut PathBuf, extension: Vec<u8>) -> bool;
fn starts_with(filepath: &PathBuf, str: Vec<u8>) -> bool;
fn file_name(filepath: &PathBuf) -> Vec<u8>;
-
- // These functions are actually in utils.rs, but I couldn't find a way to return
- // `Box<PathBuf>` from libnewsboat-ffi/src/utils.rs, so I moved the bindings here
- fn get_default_browser() -> Box<PathBuf>;
- fn resolve_tilde(path: &PathBuf) -> Box<PathBuf>;
- fn resolve_relative(reference: &PathBuf, path: &PathBuf) -> Box<PathBuf>;
- fn getcwd() -> Box<PathBuf>;
}
}
@@ -67,26 +60,6 @@ fn clone(filepath: &PathBuf) -> Box<PathBuf> {
Box::new(PathBuf(filepath.0.clone()))
}
-fn get_default_browser() -> Box<PathBuf> {
- Box::new(PathBuf(libnewsboat::utils::get_default_browser()))
-}
-
-fn resolve_tilde(path: &PathBuf) -> Box<PathBuf> {
- Box::new(PathBuf(libnewsboat::utils::resolve_tilde(path.0.clone())))
-}
-
-fn resolve_relative(reference: &PathBuf, path: &PathBuf) -> Box<PathBuf> {
- Box::new(PathBuf(libnewsboat::utils::resolve_relative(
- &reference.0,
- &path.0,
- )))
-}
-
-fn getcwd() -> Box<PathBuf> {
- let result = libnewsboat::utils::getcwd().unwrap_or_else(|_| std::path::PathBuf::new());
- Box::new(PathBuf(result))
-}
-
fn is_absolute(filepath: &PathBuf) -> bool {
filepath.0.is_absolute()
}
diff --git a/rust/libnewsboat-ffi/src/utils.rs b/rust/libnewsboat-ffi/src/utils.rs
index 06ee5736..7a4c9082 100644
--- a/rust/libnewsboat-ffi/src/utils.rs
+++ b/rust/libnewsboat-ffi/src/utils.rs
@@ -2,6 +2,7 @@ use crate::filepath::PathBuf;
use libc::{c_char, c_ulong};
use libnewsboat::utils::{self, *};
use std::ffi::{CStr, CString};
+use std::pin::Pin;
#[cxx::bridge(namespace = "newsboat::utils")]
mod ffi {
@@ -79,6 +80,10 @@ mod bridged {
fn tokenize_quoted(line: &str, delimiters: &str) -> Vec<String>;
fn is_valid_podcast_type(mimetype: &str) -> bool;
+ fn get_default_browser(mut path: Pin<&mut PathBuf>);
+ fn resolve_tilde(path: &PathBuf, mut output: Pin<&mut PathBuf>);
+ fn resolve_relative(reference: &PathBuf, path: &PathBuf, mut output: Pin<&mut PathBuf>);
+ fn getcwd(mut path: Pin<&mut PathBuf>);
fn mkdir_parents(path: &PathBuf, mode: u32) -> isize;
fn unescape_url(url: String, success: &mut bool) -> String;
@@ -189,6 +194,22 @@ fn extract_filter(line: &str) -> ffi::FilterUrlParts {
}
}
+fn get_default_browser(mut path: Pin<&mut PathBuf>) {
+ path.0 = utils::get_default_browser();
+}
+
+fn resolve_tilde(path: &PathBuf, mut output: Pin<&mut PathBuf>) {
+ output.0 = utils::resolve_tilde(path.0.clone());
+}
+
+fn resolve_relative(reference: &PathBuf, path: &PathBuf, mut output: Pin<&mut PathBuf>) {
+ output.0 = utils::resolve_relative(&reference.0, &path.0);
+}
+
+fn getcwd(mut path: Pin<&mut PathBuf>) {
+ path.0 = utils::getcwd().unwrap_or_else(|_| std::path::PathBuf::new());
+}
+
fn mkdir_parents(path: &PathBuf, mode: u32) -> isize {
match utils::mkdir_parents(&path.0, mode) {
Ok(_) => 0,
diff --git a/src/utils.cpp b/src/utils.cpp
index ca1ec9e5..182d0288 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -340,17 +340,17 @@ std::string utils::run_program(const char* argv[], const std::string& input)
Filepath utils::resolve_tilde(const Filepath& path)
{
- // The function is in utils.rs, but its binding is in filepath.rs because
- // I can't make it return `Box<PathBuf>` any other way
- return filepath::bridged::resolve_tilde(path);
+ auto output = filepath::bridged::create_empty();
+ utils::bridged::resolve_tilde(path, *output);
+ return output;
}
Filepath utils::resolve_relative(const Filepath& reference,
const Filepath& fname)
{
- // The function is in utils.rs, but its binding is in filepath.rs because
- // I can't make it return `Box<PathBuf>` any other way
- return filepath::bridged::resolve_relative(reference, fname);
+ auto output = filepath::bridged::create_empty();
+ utils::bridged::resolve_relative(reference, fname, *output);
+ return output;
}
std::string utils::replace_all(std::string str,
@@ -719,9 +719,9 @@ nonstd::optional<std::uint8_t> utils::run_non_interactively(
Filepath utils::getcwd()
{
- // The function is in utils.rs, but its binding is in filepath.rs because
- // I can't make it return `Box<PathBuf>` any other way
- return filepath::bridged::getcwd();
+ auto path = filepath::bridged::create_empty();
+ utils::bridged::getcwd(*path);
+ return path;
}
nonstd::expected<std::vector<std::string>, utils::ReadTextFileError> utils::read_text_file(
@@ -842,9 +842,9 @@ void utils::initialize_ssl_implementation(void)
Filepath utils::get_default_browser()
{
- // The function is in utils.rs, but its binding is in filepath.rs because
- // I can't make it return `Box<PathBuf>` any other way
- return filepath::bridged::get_default_browser();
+ auto path = filepath::bridged::create_empty();
+ utils::bridged::get_default_browser(*path);
+ return path;
}
std::string utils::md5hash(const std::string& input)