Support constructing a wcstring_list_ffi_t from Rust

This allows passing a vector of strings from Rust to C++
This commit is contained in:
ridiculousfish 2023-04-16 13:17:57 -07:00
parent f0360efbfa
commit 1bf29a5e13
4 changed files with 42 additions and 4 deletions

View File

@ -302,6 +302,7 @@ impl Repin for output_stream_t {}
impl Repin for parser_t {}
impl Repin for process_t {}
impl Repin for function_properties_ref_t {}
impl Repin for wcstring_list_ffi_t {}
pub use autocxx::c_int;
pub use ffi::*;

View File

@ -6,7 +6,7 @@
//! - wcharz_t: a "newtyped" pointer to a nul-terminated string, implemented in C++.
//! This is useful for FFI boundaries, to work around autocxx limitations on pointers.
pub use crate::ffi::{wchar_t, wcharz_t, wcstring_list_ffi_t};
pub use crate::ffi::{wchar_t, wcharz_t, wcstring_list_ffi_t, ToCppWString};
use crate::wchar::{wstr, WString};
use autocxx::WithinUniquePtr;
use once_cell::sync::Lazy;
@ -98,6 +98,12 @@ pub trait WCharToFFI {
fn to_ffi(&self) -> Self::Target;
}
impl ToCppWString for &wstr {
fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxWString> {
self.to_ffi()
}
}
/// WString may be converted to CxxWString.
impl WCharToFFI for WString {
type Target = cxx::UniquePtr<cxx::CxxWString>;
@ -122,6 +128,19 @@ impl WCharToFFI for wcharz_t {
}
}
/// Convert from a slice of something that can be referenced as a wstr,
/// to unique_ptr<wcstring_list_ffi_t>.
impl<T: AsRef<wstr>> WCharToFFI for [T] {
type Target = cxx::UniquePtr<wcstring_list_ffi_t>;
fn to_ffi(&self) -> cxx::UniquePtr<wcstring_list_ffi_t> {
let mut list_ptr = wcstring_list_ffi_t::create();
for s in self {
list_ptr.as_mut().unwrap().push(s.as_ref());
}
list_ptr
}
}
/// Convert from a CxxWString, in preparation for using over FFI.
pub trait WCharFromFFI<Target> {
/// Convert from a CxxWString for FFI purposes.
@ -196,7 +215,7 @@ impl<'a> AsWstr<'a> for cxx::CxxWString {
use crate::ffi_tests::add_test;
add_test!("test_wcstring_list_ffi_t", || {
use crate::ffi::wcstring_list_ffi_t;
let data: Vec<WString> = wcstring_list_ffi_t::get_test_data().from_ffi();
assert_eq!(data, vec!["foo", "bar", "baz"]);
wcstring_list_ffi_t::check_test_data(data.to_ffi());
});

View File

@ -905,3 +905,11 @@ bool file_id_t::operator<(const file_id_t &rhs) const { return this->compare_fil
wcstring_list_ffi_t wcstring_list_ffi_t::get_test_data() {
return wcstring_list_t{L"foo", L"bar", L"baz"};
}
// static
void wcstring_list_ffi_t::check_test_data(wcstring_list_ffi_t data) {
assert(data.size() == 3);
assert(data.at(0) == L"foo");
assert(data.at(1) == L"bar");
assert(data.at(2) == L"baz");
}

View File

@ -40,15 +40,25 @@ struct wcharz_t {
// A helper type for passing vectors of strings back to Rust.
// This hides the vector so that autocxx doesn't complain about templates.
struct wcstring_list_ffi_t {
wcstring_list_t vals;
wcstring_list_t vals{};
wcstring_list_ffi_t() = default;
/* implicit */ wcstring_list_ffi_t(wcstring_list_t vals) : vals(std::move(vals)) {}
size_t size() const { return vals.size(); }
const wcstring &at(size_t idx) const { return vals.at(idx); }
/// Helper function used in tests only.
/// Helper to construct one.
static std::unique_ptr<wcstring_list_ffi_t> create() {
return std::unique_ptr<wcstring_list_ffi_t>(new wcstring_list_ffi_t());
}
/// Append a string.
void push(wcstring s) { vals.push_back(std::move(s)); }
/// Helper functions used in tests only.
static wcstring_list_ffi_t get_test_data();
static void check_test_data(wcstring_list_ffi_t data);
};
class autoclose_fd_t;