Skip to content

Commit 13e4d39

Browse files
authored
Merge pull request #266 from dtolnay/vec
Implement Vec<String>
2 parents b69cb0a + 33f56ad commit 13e4d39

File tree

9 files changed

+153
-15
lines changed

9 files changed

+153
-15
lines changed

macro/src/expand.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
260260
None => quote!(::cxx::private::RustString::from_ref(#var)),
261261
Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
262262
},
263+
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
264+
None => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
265+
Some(_) => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
266+
},
263267
Type::RustVec(_) => match ty.mutability {
264268
None => quote!(::cxx::private::RustVec::from_ref(#var)),
265269
Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
@@ -332,13 +336,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
332336
Some(quote!(#call.map(|r| r.into_string())))
333337
}
334338
Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
335-
Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
339+
Type::RustVec(vec) => {
340+
if vec.inner == RustString {
341+
Some(quote!(#call.map(|r| r.into_vec_string())))
342+
} else {
343+
Some(quote!(#call.map(|r| r.into_vec())))
344+
}
345+
}
336346
Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
337347
Type::Ref(ty) => match &ty.inner {
338348
Type::Ident(ident) if ident == RustString => match ty.mutability {
339349
None => Some(quote!(#call.map(|r| r.as_string()))),
340350
Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
341351
},
352+
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
353+
None => Some(quote!(#call.map(|r| r.as_vec_string()))),
354+
Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
355+
},
342356
Type::RustVec(_) => match ty.mutability {
343357
None => Some(quote!(#call.map(|r| r.as_vec()))),
344358
Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
@@ -353,13 +367,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
353367
efn.ret.as_ref().and_then(|ret| match ret {
354368
Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
355369
Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
356-
Type::RustVec(_) => Some(quote!(#call.into_vec())),
370+
Type::RustVec(vec) => {
371+
if vec.inner == RustString {
372+
Some(quote!(#call.into_vec_string()))
373+
} else {
374+
Some(quote!(#call.into_vec()))
375+
}
376+
}
357377
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
358378
Type::Ref(ty) => match &ty.inner {
359379
Type::Ident(ident) if ident == RustString => match ty.mutability {
360380
None => Some(quote!(#call.as_string())),
361381
Some(_) => Some(quote!(#call.as_mut_string())),
362382
},
383+
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
384+
None => Some(quote!(#call.as_vec_string())),
385+
Some(_) => Some(quote!(#call.as_mut_vec_string())),
386+
},
363387
Type::RustVec(_) => match ty.mutability {
364388
None => Some(quote!(#call.as_vec())),
365389
Some(_) => Some(quote!(#call.as_mut_vec())),
@@ -508,13 +532,23 @@ fn expand_rust_function_shim_impl(
508532
quote!(::std::mem::take((*#ident).as_mut_string()))
509533
}
510534
Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
511-
Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
535+
Type::RustVec(vec) => {
536+
if vec.inner == RustString {
537+
quote!(::std::mem::take((*#ident).as_mut_vec_string()))
538+
} else {
539+
quote!(::std::mem::take((*#ident).as_mut_vec()))
540+
}
541+
}
512542
Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
513543
Type::Ref(ty) => match &ty.inner {
514544
Type::Ident(i) if i == RustString => match ty.mutability {
515545
None => quote!(#ident.as_string()),
516546
Some(_) => quote!(#ident.as_mut_string()),
517547
},
548+
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
549+
None => quote!(#ident.as_vec_string()),
550+
Some(_) => quote!(#ident.as_mut_vec_string()),
551+
},
518552
Type::RustVec(_) => match ty.mutability {
519553
None => quote!(#ident.as_vec()),
520554
Some(_) => quote!(#ident.as_mut_vec()),
@@ -549,13 +583,23 @@ fn expand_rust_function_shim_impl(
549583
Some(quote!(::cxx::private::RustString::from(#call)))
550584
}
551585
Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
552-
Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
586+
Type::RustVec(vec) => {
587+
if vec.inner == RustString {
588+
Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
589+
} else {
590+
Some(quote!(::cxx::private::RustVec::from(#call)))
591+
}
592+
}
553593
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
554594
Type::Ref(ty) => match &ty.inner {
555595
Type::Ident(ident) if ident == RustString => match ty.mutability {
556596
None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
557597
Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
558598
},
599+
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
600+
None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
601+
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
602+
},
559603
Type::RustVec(_) => match ty.mutability {
560604
None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
561605
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),

src/cxx.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
280280

281281
#define FOR_EACH_RUST_VEC(MACRO) \
282282
FOR_EACH_NUMERIC(MACRO) \
283-
MACRO(bool, bool)
283+
MACRO(bool, bool) \
284+
MACRO(string, rust::String)
284285

285286
extern "C" {
286287
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)

src/rust_vec.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use crate::rust_string::RustString;
2+
use std::mem::ManuallyDrop;
3+
14
#[repr(C)]
25
pub struct RustVec<T> {
36
repr: Vec<T>,
@@ -40,3 +43,37 @@ impl<T> RustVec<T> {
4043
self.repr.as_ptr()
4144
}
4245
}
46+
47+
impl RustVec<RustString> {
48+
pub fn from_vec_string(v: Vec<String>) -> Self {
49+
let mut v = ManuallyDrop::new(v);
50+
let ptr = v.as_mut_ptr().cast::<RustString>();
51+
let len = v.len();
52+
let cap = v.capacity();
53+
Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) })
54+
}
55+
56+
pub fn from_ref_vec_string(v: &Vec<String>) -> &Self {
57+
Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) })
58+
}
59+
60+
pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self {
61+
Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) })
62+
}
63+
64+
pub fn into_vec_string(self) -> Vec<String> {
65+
let mut v = ManuallyDrop::new(self.repr);
66+
let ptr = v.as_mut_ptr().cast::<String>();
67+
let len = v.len();
68+
let cap = v.capacity();
69+
unsafe { Vec::from_raw_parts(ptr, len, cap) }
70+
}
71+
72+
pub fn as_vec_string(&self) -> &Vec<String> {
73+
unsafe { &*(&self.repr as *const Vec<RustString> as *const Vec<String>) }
74+
}
75+
76+
pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> {
77+
unsafe { &mut *(&mut self.repr as *mut Vec<RustString> as *mut Vec<String>) }
78+
}
79+
}

src/symbols/rust_string.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ use std::ptr;
33
use std::slice;
44
use std::str;
55

6+
#[repr(C)]
7+
pub(crate) struct RustString {
8+
repr: String,
9+
}
10+
611
#[export_name = "cxxbridge03$string$new"]
712
unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
813
ptr::write(this.as_mut_ptr(), String::new());

src/symbols/rust_vec.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use super::rust_string::RustString;
12
use std::mem;
23
use std::ptr;
34

45
#[repr(C)]
5-
pub struct RustVec<T> {
6+
pub(crate) struct RustVec<T> {
67
repr: Vec<T>,
78
}
89

@@ -13,38 +14,38 @@ macro_rules! attr {
1314
};
1415
}
1516

16-
macro_rules! rust_vec_shims_for_primitive {
17-
($ty:ident) => {
17+
macro_rules! rust_vec_shims {
18+
($segment:expr, $ty:ty) => {
1819
const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
1920
const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
2021

2122
const _: () = {
2223
attr! {
23-
#[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
24+
#[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$new")]
2425
unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
2526
ptr::write(this, RustVec { repr: Vec::new() });
2627
}
2728
}
2829
attr! {
29-
#[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
30+
#[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$drop")]
3031
unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
3132
ptr::drop_in_place(this);
3233
}
3334
}
3435
attr! {
35-
#[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
36+
#[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$len")]
3637
unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
3738
(*this).repr.len()
3839
}
3940
}
4041
attr! {
41-
#[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
42+
#[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$data")]
4243
unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
4344
(*this).repr.as_ptr()
4445
}
4546
}
4647
attr! {
47-
#[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
48+
#[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$stride")]
4849
unsafe extern "C" fn __stride() -> usize {
4950
mem::size_of::<$ty>()
5051
}
@@ -53,6 +54,12 @@ macro_rules! rust_vec_shims_for_primitive {
5354
};
5455
}
5556

57+
macro_rules! rust_vec_shims_for_primitive {
58+
($ty:ident) => {
59+
rust_vec_shims!(stringify!($ty), $ty);
60+
};
61+
}
62+
5663
rust_vec_shims_for_primitive!(bool);
5764
rust_vec_shims_for_primitive!(u8);
5865
rust_vec_shims_for_primitive!(u16);
@@ -64,3 +71,5 @@ rust_vec_shims_for_primitive!(i32);
6471
rust_vec_shims_for_primitive!(i64);
6572
rust_vec_shims_for_primitive!(f32);
6673
rust_vec_shims_for_primitive!(f64);
74+
75+
rust_vec_shims!("string", RustString);

syntax/check.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
9292

9393
match Atom::from(ident) {
9494
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
95-
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
96-
Some(Bool) | Some(RustString) => { /* todo */ }
95+
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
96+
| Some(RustString) => return,
97+
Some(Bool) => { /* todo */ }
9798
Some(CxxString) => {}
9899
}
99100
}

tests/ffi/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub mod ffi {
4646
fn c_return_rust_vec() -> Vec<u8>;
4747
fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
4848
fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
49+
fn c_return_rust_vec_string() -> Vec<String>;
4950
fn c_return_identity(_: usize) -> usize;
5051
fn c_return_sum(_: usize, _: usize) -> usize;
5152
fn c_return_enum(n: u16) -> Enum;
@@ -65,10 +66,12 @@ pub mod ffi {
6566
fn c_take_ref_vector(v: &CxxVector<u8>);
6667
fn c_take_rust_vec(v: Vec<u8>);
6768
fn c_take_rust_vec_shared(v: Vec<Shared>);
69+
fn c_take_rust_vec_string(v: Vec<String>);
6870
fn c_take_rust_vec_index(v: Vec<u8>);
6971
fn c_take_rust_vec_shared_index(v: Vec<Shared>);
7072
fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
7173
fn c_take_ref_rust_vec(v: &Vec<u8>);
74+
fn c_take_ref_rust_vec_string(v: &Vec<String>);
7275
fn c_take_ref_rust_vec_index(v: &Vec<u8>);
7376
fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
7477
/*
@@ -87,6 +90,7 @@ pub mod ffi {
8790
fn c_try_return_rust_string() -> Result<String>;
8891
fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
8992
fn c_try_return_rust_vec() -> Result<Vec<u8>>;
93+
fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
9094
fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
9195

9296
fn get(self: &C) -> usize;
@@ -121,6 +125,7 @@ pub mod ffi {
121125
fn r_return_rust_string() -> String;
122126
fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
123127
fn r_return_rust_vec() -> Vec<u8>;
128+
fn r_return_rust_vec_string() -> Vec<String>;
124129
fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
125130
fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
126131
fn r_return_identity(_: usize) -> usize;
@@ -138,7 +143,9 @@ pub mod ffi {
138143
fn r_take_rust_string(s: String);
139144
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
140145
fn r_take_rust_vec(v: Vec<u8>);
146+
fn r_take_rust_vec_string(v: Vec<String>);
141147
fn r_take_ref_rust_vec(v: &Vec<u8>);
148+
fn r_take_ref_rust_vec_string(v: &Vec<String>);
142149
fn r_take_enum(e: Enum);
143150

144151
fn r_try_return_void() -> Result<()>;
@@ -224,6 +231,10 @@ fn r_return_rust_vec() -> Vec<u8> {
224231
Vec::new()
225232
}
226233

234+
fn r_return_rust_vec_string() -> Vec<String> {
235+
Vec::new()
236+
}
237+
227238
fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
228239
let _ = shared;
229240
unimplemented!()
@@ -297,10 +308,18 @@ fn r_take_rust_vec(v: Vec<u8>) {
297308
let _ = v;
298309
}
299310

311+
fn r_take_rust_vec_string(v: Vec<String>) {
312+
let _ = v;
313+
}
314+
300315
fn r_take_ref_rust_vec(v: &Vec<u8>) {
301316
let _ = v;
302317
}
303318

319+
fn r_take_ref_rust_vec_string(v: &Vec<String>) {
320+
let _ = v;
321+
}
322+
304323
fn r_take_enum(e: ffi::Enum) {
305324
let _ = e;
306325
}

tests/ffi/tests.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
119119
throw std::runtime_error("unimplemented");
120120
}
121121

122+
rust::Vec<rust::String> c_return_rust_vec_string() {
123+
throw std::runtime_error("unimplemented");
124+
}
125+
122126
size_t c_return_identity(size_t n) { return n; }
123127

124128
size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
@@ -241,6 +245,11 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
241245
}
242246
}
243247

248+
void c_take_rust_vec_string(rust::Vec<rust::String> v) {
249+
(void)v;
250+
cxx_test_suite_set_correct();
251+
}
252+
244253
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
245254
// Exercise requirements of ForwardIterator
246255
// https://en.cppreference.com/w/cpp/named_req/ForwardIterator
@@ -267,6 +276,11 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
267276
}
268277
}
269278

279+
void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
280+
(void)v;
281+
cxx_test_suite_set_correct();
282+
}
283+
270284
void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
271285
if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
272286
v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
@@ -323,6 +337,10 @@ rust::Vec<uint8_t> c_try_return_rust_vec() {
323337
throw std::runtime_error("unimplemented");
324338
}
325339

340+
rust::Vec<rust::String> c_try_return_rust_vec_string() {
341+
throw std::runtime_error("unimplemented");
342+
}
343+
326344
const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
327345
(void)c;
328346
throw std::runtime_error("unimplemented");

0 commit comments

Comments
 (0)