Skip to content

cxx_vector: add API for reserving capacity and retrieving it #1274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions gen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1922,6 +1922,24 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
writeln!(out, " return s.size();");
writeln!(out, "}}");

begin_function_definition(out);
writeln!(
out,
"void cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t capacity) noexcept {{",
instance, inner,
);
writeln!(out, " s->reserve(capacity);");
writeln!(out, "}}");

begin_function_definition(out);
writeln!(
out,
"::std::size_t cxxbridge1$std$vector${}$capacity(::std::vector<{}> const &s) noexcept {{",
instance, inner,
);
writeln!(out, " return s.capacity();");
writeln!(out, "}}");

begin_function_definition(out);
writeln!(
out,
Expand Down
19 changes: 19 additions & 0 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,8 @@ fn expand_cxx_vector(
let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
let link_new = format!("{}new", prefix);
let link_size = format!("{}size", prefix);
let link_reserve = format!("{}reserve", prefix);
let link_capacity = format!("{}capacity", prefix);
let link_get_unchecked = format!("{}get_unchecked", prefix);
let link_push_back = format!("{}push_back", prefix);
let link_pop_back = format!("{}pop_back", prefix);
Expand Down Expand Up @@ -1759,6 +1761,23 @@ fn expand_cxx_vector(
}
unsafe { __vector_size(v) }
}
unsafe fn __vector_reserve(v: *mut ::cxx::CxxVector<Self>, capacity: usize) {
extern "C" {
#[link_name = #link_reserve]
fn __vector_reserve #impl_generics(
_: *mut ::cxx::CxxVector<#elem #ty_generics>,
_: usize
);
}
__vector_reserve(v, capacity)
}
fn __vector_capacity(v: &::cxx::CxxVector<Self>) -> usize {
extern "C" {
#[link_name = #link_capacity]
fn __vector_capacity #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
}
unsafe { __vector_capacity(v) }
}
unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
extern "C" {
#[link_name = #link_get_unchecked]
Expand Down
8 changes: 8 additions & 0 deletions src/cxx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,14 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
const std::vector<CXX_TYPE> &s) noexcept { \
return s.size(); \
} \
void cxxbridge1$std$vector$##RUST_TYPE##$reserve( \
std::vector<CXX_TYPE> *s, std::size_t capacity) noexcept { \
s->reserve(capacity); \
} \
std::size_t cxxbridge1$std$vector$##RUST_TYPE##$capacity( \
const std::vector<CXX_TYPE> &s) noexcept { \
return s.capacity(); \
} \
CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
return &(*s)[pos]; \
Expand Down
36 changes: 36 additions & 0 deletions src/cxx_vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ where
self.len() == 0
}

/// Increase the capacity of the vector.
///
/// Matches the behavior of C++ [std::vector\<T\>::reserve][reserve].
///
/// [reserve]: https://en.cppreference.com/w/cpp/container/vector/reserve
pub fn reserve(self: Pin<&mut Self>, capacity: usize) {
unsafe { T::__vector_reserve(self.get_unchecked_mut(), capacity) }
}

/// Returns the number of elements that the vector has currently allocated space for.
///
/// Matches the behavior of C++ [std::vector\<T\>::capacity][capacity].
///
/// [capacity]: https://en.cppreference.com/w/cpp/container/vector/capacity
pub fn capacity(&self) -> usize {
T::__vector_capacity(self)
}

/// Returns a reference to an element at the given position, or `None` if
/// out of bounds.
pub fn get(&self, pos: usize) -> Option<&T> {
Expand Down Expand Up @@ -346,6 +364,10 @@ pub unsafe trait VectorElement: Sized {
#[doc(hidden)]
fn __vector_size(v: &CxxVector<Self>) -> usize;
#[doc(hidden)]
unsafe fn __vector_reserve(v: *mut CxxVector<Self>, capacity: usize);
#[doc(hidden)]
fn __vector_capacity(v: &CxxVector<Self>) -> usize;
#[doc(hidden)]
unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
#[doc(hidden)]
unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut ManuallyDrop<Self>) {
Expand Down Expand Up @@ -418,6 +440,20 @@ macro_rules! impl_vector_element {
}
unsafe { __vector_size(v) }
}
unsafe fn __vector_reserve(v: *mut CxxVector<$ty>, capacity: usize) {
extern "C" {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$reserve")]
fn __vector_reserve(_: *mut CxxVector<$ty>, _: usize);
}
unsafe { __vector_reserve(v, capacity) }
}
fn __vector_capacity(v: &CxxVector<$ty>) -> usize {
extern "C" {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$capacity")]
fn __vector_capacity(_: &CxxVector<$ty>) -> usize;
}
unsafe { __vector_capacity(v) }
}
unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
extern "C" {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
Expand Down