Implement Vec<String>
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ab1206c..0869c2c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -260,6 +260,10 @@
None => quote!(::cxx::private::RustString::from_ref(#var)),
Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
},
+ Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+ None => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
+ Some(_) => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
+ },
Type::RustVec(_) => match ty.mutability {
None => quote!(::cxx::private::RustVec::from_ref(#var)),
Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
@@ -332,13 +336,23 @@
Some(quote!(#call.map(|r| r.into_string())))
}
Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
- Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
+ Type::RustVec(vec) => {
+ if vec.inner == RustString {
+ Some(quote!(#call.map(|r| r.into_vec_string())))
+ } else {
+ Some(quote!(#call.map(|r| r.into_vec())))
+ }
+ }
Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
Type::Ref(ty) => match &ty.inner {
Type::Ident(ident) if ident == RustString => match ty.mutability {
None => Some(quote!(#call.map(|r| r.as_string()))),
Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
},
+ Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+ None => Some(quote!(#call.map(|r| r.as_vec_string()))),
+ Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
+ },
Type::RustVec(_) => match ty.mutability {
None => Some(quote!(#call.map(|r| r.as_vec()))),
Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
@@ -353,13 +367,23 @@
efn.ret.as_ref().and_then(|ret| match ret {
Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
- Type::RustVec(_) => Some(quote!(#call.into_vec())),
+ Type::RustVec(vec) => {
+ if vec.inner == RustString {
+ Some(quote!(#call.into_vec_string()))
+ } else {
+ Some(quote!(#call.into_vec()))
+ }
+ }
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
Type::Ref(ty) => match &ty.inner {
Type::Ident(ident) if ident == RustString => match ty.mutability {
None => Some(quote!(#call.as_string())),
Some(_) => Some(quote!(#call.as_mut_string())),
},
+ Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+ None => Some(quote!(#call.as_vec_string())),
+ Some(_) => Some(quote!(#call.as_mut_vec_string())),
+ },
Type::RustVec(_) => match ty.mutability {
None => Some(quote!(#call.as_vec())),
Some(_) => Some(quote!(#call.as_mut_vec())),
@@ -508,13 +532,23 @@
quote!(::std::mem::take((*#ident).as_mut_string()))
}
Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
- Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
+ Type::RustVec(vec) => {
+ if vec.inner == RustString {
+ quote!(::std::mem::take((*#ident).as_mut_vec_string()))
+ } else {
+ quote!(::std::mem::take((*#ident).as_mut_vec()))
+ }
+ }
Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
Type::Ref(ty) => match &ty.inner {
Type::Ident(i) if i == RustString => match ty.mutability {
None => quote!(#ident.as_string()),
Some(_) => quote!(#ident.as_mut_string()),
},
+ Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+ None => quote!(#ident.as_vec_string()),
+ Some(_) => quote!(#ident.as_mut_vec_string()),
+ },
Type::RustVec(_) => match ty.mutability {
None => quote!(#ident.as_vec()),
Some(_) => quote!(#ident.as_mut_vec()),
@@ -549,13 +583,23 @@
Some(quote!(::cxx::private::RustString::from(#call)))
}
Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
- Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
+ Type::RustVec(vec) => {
+ if vec.inner == RustString {
+ Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
+ } else {
+ Some(quote!(::cxx::private::RustVec::from(#call)))
+ }
+ }
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
Type::Ref(ty) => match &ty.inner {
Type::Ident(ident) if ident == RustString => match ty.mutability {
None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
},
+ Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+ None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
+ Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
+ },
Type::RustVec(_) => match ty.mutability {
None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
diff --git a/src/cxx.cc b/src/cxx.cc
index b953904..e00fd6a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -280,7 +280,8 @@
#define FOR_EACH_RUST_VEC(MACRO) \
FOR_EACH_NUMERIC(MACRO) \
- MACRO(bool, bool)
+ MACRO(bool, bool) \
+ MACRO(string, rust::String)
extern "C" {
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 9ff4bbf..5e7082a 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,3 +1,6 @@
+use crate::rust_string::RustString;
+use std::mem::ManuallyDrop;
+
#[repr(C)]
pub struct RustVec<T> {
repr: Vec<T>,
@@ -40,3 +43,37 @@
self.repr.as_ptr()
}
}
+
+impl RustVec<RustString> {
+ pub fn from_vec_string(v: Vec<String>) -> Self {
+ let mut v = ManuallyDrop::new(v);
+ let ptr = v.as_mut_ptr().cast::<RustString>();
+ let len = v.len();
+ let cap = v.capacity();
+ Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) })
+ }
+
+ pub fn from_ref_vec_string(v: &Vec<String>) -> &Self {
+ Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) })
+ }
+
+ pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self {
+ Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) })
+ }
+
+ pub fn into_vec_string(self) -> Vec<String> {
+ let mut v = ManuallyDrop::new(self.repr);
+ let ptr = v.as_mut_ptr().cast::<String>();
+ let len = v.len();
+ let cap = v.capacity();
+ unsafe { Vec::from_raw_parts(ptr, len, cap) }
+ }
+
+ pub fn as_vec_string(&self) -> &Vec<String> {
+ unsafe { &*(&self.repr as *const Vec<RustString> as *const Vec<String>) }
+ }
+
+ pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> {
+ unsafe { &mut *(&mut self.repr as *mut Vec<RustString> as *mut Vec<String>) }
+ }
+}
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 63d4ba7..d8e0f4a 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -3,6 +3,11 @@
use std::slice;
use std::str;
+#[repr(C)]
+pub(crate) struct RustString {
+ repr: String,
+}
+
#[export_name = "cxxbridge03$string$new"]
unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
ptr::write(this.as_mut_ptr(), String::new());
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 9ce87ab..5465471 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,8 +1,9 @@
+use super::rust_string::RustString;
use std::mem;
use std::ptr;
#[repr(C)]
-pub struct RustVec<T> {
+pub(crate) struct RustVec<T> {
repr: Vec<T>,
}
@@ -13,38 +14,38 @@
};
}
-macro_rules! rust_vec_shims_for_primitive {
- ($ty:ident) => {
+macro_rules! rust_vec_shims {
+ ($segment:expr, $ty:ty) => {
const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
const _: () = {
attr! {
- #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
+ #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$new")]
unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
ptr::write(this, RustVec { repr: Vec::new() });
}
}
attr! {
- #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
+ #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$drop")]
unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
ptr::drop_in_place(this);
}
}
attr! {
- #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
+ #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$len")]
unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
(*this).repr.len()
}
}
attr! {
- #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
+ #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$data")]
unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
(*this).repr.as_ptr()
}
}
attr! {
- #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
+ #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$stride")]
unsafe extern "C" fn __stride() -> usize {
mem::size_of::<$ty>()
}
@@ -53,6 +54,12 @@
};
}
+macro_rules! rust_vec_shims_for_primitive {
+ ($ty:ident) => {
+ rust_vec_shims!(stringify!($ty), $ty);
+ };
+}
+
rust_vec_shims_for_primitive!(bool);
rust_vec_shims_for_primitive!(u8);
rust_vec_shims_for_primitive!(u16);
@@ -64,3 +71,5 @@
rust_vec_shims_for_primitive!(i64);
rust_vec_shims_for_primitive!(f32);
rust_vec_shims_for_primitive!(f64);
+
+rust_vec_shims!("string", RustString);
diff --git a/syntax/check.rs b/syntax/check.rs
index c54430c..71fab3b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -92,8 +92,9 @@
match Atom::from(ident) {
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
- | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
- Some(Bool) | Some(RustString) => { /* todo */ }
+ | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+ | Some(RustString) => return,
+ Some(Bool) => { /* todo */ }
Some(CxxString) => {}
}
}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d69163a..cb688f3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -46,6 +46,7 @@
fn c_return_rust_vec() -> Vec<u8>;
fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
+ fn c_return_rust_vec_string() -> Vec<String>;
fn c_return_identity(_: usize) -> usize;
fn c_return_sum(_: usize, _: usize) -> usize;
fn c_return_enum(n: u16) -> Enum;
@@ -65,10 +66,12 @@
fn c_take_ref_vector(v: &CxxVector<u8>);
fn c_take_rust_vec(v: Vec<u8>);
fn c_take_rust_vec_shared(v: Vec<Shared>);
+ fn c_take_rust_vec_string(v: Vec<String>);
fn c_take_rust_vec_index(v: Vec<u8>);
fn c_take_rust_vec_shared_index(v: Vec<Shared>);
fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
fn c_take_ref_rust_vec(v: &Vec<u8>);
+ fn c_take_ref_rust_vec_string(v: &Vec<String>);
fn c_take_ref_rust_vec_index(v: &Vec<u8>);
fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
/*
@@ -87,6 +90,7 @@
fn c_try_return_rust_string() -> Result<String>;
fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
fn c_try_return_rust_vec() -> Result<Vec<u8>>;
+ fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
fn get(self: &C) -> usize;
@@ -121,6 +125,7 @@
fn r_return_rust_string() -> String;
fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
fn r_return_rust_vec() -> Vec<u8>;
+ fn r_return_rust_vec_string() -> Vec<String>;
fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
fn r_return_identity(_: usize) -> usize;
@@ -138,7 +143,9 @@
fn r_take_rust_string(s: String);
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
fn r_take_rust_vec(v: Vec<u8>);
+ fn r_take_rust_vec_string(v: Vec<String>);
fn r_take_ref_rust_vec(v: &Vec<u8>);
+ fn r_take_ref_rust_vec_string(v: &Vec<String>);
fn r_take_enum(e: Enum);
fn r_try_return_void() -> Result<()>;
@@ -224,6 +231,10 @@
Vec::new()
}
+fn r_return_rust_vec_string() -> Vec<String> {
+ Vec::new()
+}
+
fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
let _ = shared;
unimplemented!()
@@ -297,10 +308,18 @@
let _ = v;
}
+fn r_take_rust_vec_string(v: Vec<String>) {
+ let _ = v;
+}
+
fn r_take_ref_rust_vec(v: &Vec<u8>) {
let _ = v;
}
+fn r_take_ref_rust_vec_string(v: &Vec<String>) {
+ let _ = v;
+}
+
fn r_take_enum(e: ffi::Enum) {
let _ = e;
}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b213930..b45e8ae 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -119,6 +119,10 @@
throw std::runtime_error("unimplemented");
}
+rust::Vec<rust::String> c_return_rust_vec_string() {
+ throw std::runtime_error("unimplemented");
+}
+
size_t c_return_identity(size_t n) { return n; }
size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
@@ -241,6 +245,11 @@
}
}
+void c_take_rust_vec_string(rust::Vec<rust::String> v) {
+ (void)v;
+ cxx_test_suite_set_correct();
+}
+
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
// Exercise requirements of ForwardIterator
// https://en.cppreference.com/w/cpp/named_req/ForwardIterator
@@ -267,6 +276,11 @@
}
}
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
+ (void)v;
+ cxx_test_suite_set_correct();
+}
+
void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
@@ -323,6 +337,10 @@
throw std::runtime_error("unimplemented");
}
+rust::Vec<rust::String> c_try_return_rust_vec_string() {
+ throw std::runtime_error("unimplemented");
+}
+
const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
(void)c;
throw std::runtime_error("unimplemented");
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fe644eb..0efbd62 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -50,6 +50,7 @@
rust::Vec<uint8_t> c_return_rust_vec();
const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c);
+rust::Vec<rust::String> c_return_rust_vec_string();
size_t c_return_identity(size_t n);
size_t c_return_sum(size_t n1, size_t n2);
Enum c_return_enum(uint16_t n);
@@ -71,9 +72,11 @@
void c_take_rust_vec(rust::Vec<uint8_t> v);
void c_take_rust_vec_index(rust::Vec<uint8_t> v);
void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_string(rust::Vec<rust::String> v);
void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
/*
@@ -92,6 +95,7 @@
rust::String c_try_return_rust_string();
std::unique_ptr<std::string> c_try_return_unique_ptr_string();
rust::Vec<uint8_t> c_try_return_rust_vec();
+rust::Vec<rust::String> c_try_return_rust_vec_string();
const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
} // namespace tests