Add Vec<T>::truncate to C++ API

Based on the model of #951, which added `Vec<T>::clear`. The `truncate`
method is the more general form of clear.

(If we wanted to, we could delete the binding for `clear` and implement
`clear` as a call to `truncate(0)` on the C++ side, but seemed worth
leaving in in case the Rust `clear` implementation one day gets
smarter.)
This commit is contained in:
Nikhil Benesch 2021-12-26 15:18:50 -05:00
parent d662b6cbd4
commit e3918b5422
No known key found for this signature in database
GPG Key ID: 786B2BFE892C5275
11 changed files with 56 additions and 0 deletions

View File

@ -47,6 +47,7 @@ public:
void push_back(T &&value);
template <typename... Args>
void emplace_back(Args &&...args);
void truncate(size_t len);
void clear();
class iterator;

View File

@ -1475,6 +1475,11 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
"void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
instance, inner,
);
writeln!(
out,
"void cxxbridge1$rust_vec${}$truncate(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
instance, inner,
);
writeln!(
out,
"void cxxbridge1$rust_vec${}$clear(::rust::Vec<{}> *ptr) noexcept;",
@ -1591,6 +1596,16 @@ fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
);
writeln!(out, "}}");
writeln!(out, "template <>");
begin_function_definition(out);
writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner,);
writeln!(
out,
" return cxxbridge1$rust_vec${}$truncate(this, len);",
instance,
);
writeln!(out, "}}");
writeln!(out, "template <>");
begin_function_definition(out);
writeln!(out, "void Vec<{}>::clear() {{", inner);

View File

@ -324,6 +324,7 @@ public:
void push_back(T &&value);
template <typename... Args>
void emplace_back(Args &&...args);
void truncate(std::size_t len);
void clear();
using iterator = typename Slice<T>::iterator;

View File

@ -1288,6 +1288,7 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
let link_data = format!("{}data", link_prefix);
let link_reserve_total = format!("{}reserve_total", link_prefix);
let link_set_len = format!("{}set_len", link_prefix);
let link_truncate = format!("{}truncate", link_prefix);
let link_clear = format!("{}clear", link_prefix);
let local_prefix = format_ident!("{}__vec_", elem);
@ -1298,6 +1299,7 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
let local_data = format_ident!("{}data", local_prefix);
let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
let local_set_len = format_ident!("{}set_len", local_prefix);
let local_truncate = format_ident!("{}truncate", local_prefix);
let local_clear = format_ident!("{}clear", local_prefix);
let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
@ -1353,6 +1355,12 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
(*this).set_len(len);
}
#[doc(hidden)]
#[export_name = #link_truncate]
unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
::cxx::private::prevent_unwind(__fn, || (*this).truncate(len));
}
#[doc(hidden)]
#[export_name = #link_clear]
unsafe extern "C" fn #local_clear #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);

View File

@ -569,6 +569,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
std::size_t len) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \
std::size_t len) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$clear( \
rust::Vec<CXX_TYPE> *ptr) noexcept;
@ -602,6 +604,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
} \
template <> \
void Vec<CXX_TYPE>::truncate(std::size_t len) { \
cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \
} \
template <> \
void Vec<CXX_TYPE>::clear() { \
cxxbridge1$rust_vec$##RUST_TYPE##$clear(this); \
}

View File

@ -69,6 +69,10 @@ impl<T> RustVec<T> {
unsafe { self.as_mut_vec().set_len(len) }
}
pub fn truncate(&mut self, len: usize) {
self.as_mut_vec().truncate(len)
}
pub fn clear(&mut self) {
self.as_mut_vec().clear();
}

View File

@ -56,6 +56,12 @@ macro_rules! rust_vec_shims {
unsafe { (*this).set_len(len) }
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$truncate")]
unsafe extern "C" fn __truncate(this: *mut RustVec<$ty>, len: usize) {
unsafe { (*this).truncate(len) }
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$clear")]
unsafe extern "C" fn __clear(this: *mut RustVec<$ty>) {

View File

@ -149,6 +149,7 @@ pub mod ffi {
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_push(v: Vec<Shared>);
fn c_take_rust_vec_shared_truncate(v: Vec<Shared>);
fn c_take_rust_vec_shared_clear(v: Vec<Shared>);
fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
fn c_take_rust_vec_shared_sort(v: Vec<Shared>);

View File

@ -452,6 +452,16 @@ void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
}
}
void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v) {
v.truncate(1);
if (v.size() == 1) {
v.truncate(0);
if (v.size() == 0) {
cxx_test_suite_set_correct();
}
}
}
void c_take_rust_vec_shared_clear(rust::Vec<Shared> v) {
v.clear();
if (v.size() == 0) {

View File

@ -152,6 +152,7 @@ void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> 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_push(rust::Vec<Shared> v);
void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v);
void c_take_rust_vec_shared_clear(rust::Vec<Shared> v);
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
void c_take_rust_vec_shared_sort(rust::Vec<Shared> v);

View File

@ -167,6 +167,9 @@ fn test_c_take() {
check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_truncate(
shared_test_vec.clone()
));
check!(ffi::c_take_rust_vec_shared_clear(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_forward_iterator(
shared_test_vec,