From 1c68da76432b3a7b1c12693c9229be15d6a07206 Mon Sep 17 00:00:00 2001 From: jhonboy121 Date: Tue, 3 Oct 2023 23:02:34 +0530 Subject: [PATCH] cxx_vector: add API for reserving capacity and retrieving it Signed-off-by: jhonboy121 --- gen/src/write.rs | 18 ++++++++++++++++++ macro/src/expand.rs | 19 +++++++++++++++++++ src/cxx.cc | 8 ++++++++ src/cxx_vector.rs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/gen/src/write.rs b/gen/src/write.rs index 8eef0a76b..6f8ace542 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -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, diff --git a/macro/src/expand.rs b/macro/src/expand.rs index bcc660db5..9a452030e 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -1615,6 +1615,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); @@ -1687,6 +1689,23 @@ fn expand_cxx_vector( } unsafe { __vector_size(v) } } + unsafe fn __vector_reserve(v: *mut ::cxx::CxxVector, 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) -> 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, pos: usize) -> *mut Self { extern "C" { #[link_name = #link_get_unchecked] diff --git a/src/cxx.cc b/src/cxx.cc index 2522d61aa..85ae0a9c2 100644 --- a/src/cxx.cc +++ b/src/cxx.cc @@ -600,6 +600,14 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), const std::vector &s) noexcept { \ return s.size(); \ } \ + void cxxbridge1$std$vector$##RUST_TYPE##$reserve( \ + std::vector *s, std::size_t capacity) noexcept { \ + s->reserve(capacity); \ + } \ + std::size_t cxxbridge1$std$vector$##RUST_TYPE##$capacity( \ + const std::vector &s) noexcept { \ + return s.capacity(); \ + } \ CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \ std::vector *s, std::size_t pos) noexcept { \ return &(*s)[pos]; \ diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs index 242e30ed8..78f7ce768 100644 --- a/src/cxx_vector.rs +++ b/src/cxx_vector.rs @@ -62,6 +62,24 @@ where self.len() == 0 } + /// Increase the capacity of the vector. + /// + /// Matches the behavior of C++ [std::vector\::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\::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> { @@ -346,6 +364,10 @@ pub unsafe trait VectorElement: Sized { #[doc(hidden)] fn __vector_size(v: &CxxVector) -> usize; #[doc(hidden)] + unsafe fn __vector_reserve(v: *mut CxxVector, capacity: usize); + #[doc(hidden)] + fn __vector_capacity(v: &CxxVector) -> usize; + #[doc(hidden)] unsafe fn __get_unchecked(v: *mut CxxVector, pos: usize) -> *mut Self; #[doc(hidden)] unsafe fn __push_back(v: Pin<&mut CxxVector>, value: &mut ManuallyDrop) { @@ -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")]