Add rust::Vec push_back and emplace_back
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 72b411c..41d037a 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -69,6 +69,7 @@
include.array = true;
include.new = true;
include.type_traits = true;
+ include.utility = true;
builtin.panic = true;
builtin.unsafe_bitcopy = true;
}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 69b9f2e..5fe8ee3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1078,6 +1078,16 @@
);
writeln!(
out,
+ "void cxxbridge05$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
+ instance, inner,
+ );
+ writeln!(
+ out,
+ "void cxxbridge05$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
+ instance, inner,
+ );
+ writeln!(
+ out,
"size_t cxxbridge05$rust_vec${}$stride() noexcept;",
instance,
);
@@ -1133,6 +1143,28 @@
writeln!(out, "}}");
writeln!(out, "template <>");
+ writeln!(
+ out,
+ "void Vec<{}>::reserve_total(size_t cap) noexcept {{",
+ inner,
+ );
+ writeln!(
+ out,
+ " return cxxbridge05$rust_vec${}$reserve_total(this, cap);",
+ instance,
+ );
+ writeln!(out, "}}");
+
+ writeln!(out, "template <>");
+ writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
+ writeln!(
+ out,
+ " return cxxbridge05$rust_vec${}$set_len(this, len);",
+ instance,
+ );
+ writeln!(out, "}}");
+
+ writeln!(out, "template <>");
writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
writeln!(out, " return cxxbridge05$rust_vec${}$stride();", instance);
writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index 0313d34..7dfbbca 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -169,6 +169,7 @@
size_t size() const noexcept;
bool empty() const noexcept;
const T *data() const noexcept;
+ T *data() noexcept;
const T &operator[](size_t n) const noexcept;
const T &at(size_t n) const;
@@ -176,6 +177,12 @@
const T &front() const;
const T &back() const;
+ void reserve(size_t new_cap);
+ void push_back(const T &value);
+ void push_back(T &&value);
+ template <class... Args>
+ void emplace_back(Args &&... args);
+
class const_iterator final {
public:
using difference_type = ptrdiff_t;
@@ -207,6 +214,8 @@
private:
static size_t stride() noexcept;
+ void reserve_total(size_t cap) noexcept;
+ void set_len(size_t len) noexcept;
void drop() noexcept;
// Size and alignment statically verified by rust_vec.rs.
@@ -498,6 +507,11 @@
}
template <typename T>
+T *Vec<T>::data() noexcept {
+ return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());
+}
+
+template <typename T>
const T &Vec<T>::operator[](size_t n) const noexcept {
auto data = reinterpret_cast<const char *>(this->data());
return *reinterpret_cast<const T *>(data + n * this->stride());
@@ -522,6 +536,32 @@
}
template <typename T>
+void Vec<T>::reserve(size_t new_cap) {
+ this->reserve_total(new_cap);
+}
+
+template <typename T>
+void Vec<T>::push_back(const T &value) {
+ this->emplace_back(value);
+}
+
+template <typename T>
+void Vec<T>::push_back(T &&value) {
+ this->emplace_back(std::move(value));
+}
+
+template <typename T>
+template <typename... Args>
+void Vec<T>::emplace_back(Args &&... args) {
+ auto size = this->size();
+ this->reserve_total(size + 1);
+ ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
+ size * this->stride()))
+ T(std::forward<Args>(args)...);
+ this->set_len(size + 1);
+}
+
+template <typename T>
const T &Vec<T>::const_iterator::operator*() const noexcept {
return *static_cast<const T *>(this->pos);
}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b5d3067..0ae7168 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -727,6 +727,8 @@
let link_drop = format!("{}drop", link_prefix);
let link_len = format!("{}len", link_prefix);
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_stride = format!("{}stride", link_prefix);
let local_prefix = format_ident!("{}__vec_", elem.rust);
@@ -734,6 +736,8 @@
let local_drop = format_ident!("{}drop", local_prefix);
let local_len = format_ident!("{}len", local_prefix);
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_stride = format_ident!("{}stride", local_prefix);
let span = elem.span();
@@ -759,6 +763,16 @@
(*this).as_ptr()
}
#[doc(hidden)]
+ #[export_name = #link_reserve_total]
+ unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
+ (*this).reserve_total(cap);
+ }
+ #[doc(hidden)]
+ #[export_name = #link_set_len]
+ unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
+ (*this).set_len(len);
+ }
+ #[doc(hidden)]
#[export_name = #link_stride]
unsafe extern "C" fn #local_stride() -> usize {
::std::mem::size_of::<#elem>()
diff --git a/src/cxx.cc b/src/cxx.cc
index 5877b35..cbaecbf 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -267,6 +267,10 @@
const rust::Vec<CXX_TYPE> *ptr) noexcept; \
const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data( \
const rust::Vec<CXX_TYPE> *ptr) noexcept; \
+ void cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total( \
+ rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept; \
+ void cxxbridge05$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
+ size_t len) noexcept; \
size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
@@ -287,6 +291,14 @@
return cxxbridge05$rust_vec$##RUST_TYPE##$data(this); \
} \
template <> \
+ void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept { \
+ cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(this, cap); \
+ } \
+ template <> \
+ void Vec<CXX_TYPE>::set_len(size_t len) noexcept { \
+ cxxbridge05$rust_vec$##RUST_TYPE##$set_len(this, len); \
+ } \
+ template <> \
size_t Vec<CXX_TYPE>::stride() noexcept { \
return cxxbridge05$rust_vec$##RUST_TYPE##$stride(); \
}
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index f1a7741..8ddc4a7 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -44,6 +44,17 @@
pub fn as_ptr(&self) -> *const T {
self.repr.as_ptr()
}
+
+ pub fn reserve_total(&mut self, cap: usize) {
+ let len = self.repr.len();
+ if cap > len {
+ self.repr.reserve(cap - len);
+ }
+ }
+
+ pub unsafe fn set_len(&mut self, len: usize) {
+ self.repr.set_len(len);
+ }
}
impl RustVec<RustString> {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 00a7f16..90fbc54 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -35,6 +35,18 @@
}
}
attr! {
+ #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$reserve_total")]
+ unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, cap: usize) {
+ (*this).reserve_total(cap);
+ }
+ }
+ attr! {
+ #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$set_len")]
+ unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) {
+ (*this).repr.set_len(len);
+ }
+ }
+ attr! {
#[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$stride")]
unsafe extern "C" fn __stride() -> usize {
mem::size_of::<$ty>()
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7461d66..9e67d7f 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -168,6 +168,7 @@
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_push(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>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c3c797a..2305766 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -356,6 +356,14 @@
}
}
+void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
+ v.push_back(Shared{3});
+ v.emplace_back(Shared{2});
+ if (v[v.size() - 2].z == 3 && v.back().z == 2) {
+ cxx_test_suite_set_correct();
+ }
+}
+
void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
if (sum == 200) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7fc5633..2217c36 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -130,6 +130,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_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);
diff --git a/tests/test.rs b/tests/test.rs
index a2c64c3..2bae4d8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -133,6 +133,7 @@
let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }];
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_forward_iterator(
shared_test_vec,
));