diff options
author | David Tolnay <dtolnay@gmail.com> | 2021-08-27 13:39:10 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-27 13:39:10 -0700 |
commit | 4e0ac983992f9bb59bf2a457eb778e42582c85b4 (patch) | |
tree | 2e006139377f982ee64bc5dbdee715d8b336915f | |
parent | 800d98989532e519d422b94544e1421c9cb73006 (diff) | |
parent | 6f3f4bb7ee2e42d8bb10d3a963cd4b0b5f1733c8 (diff) | |
download | cxx-4e0ac983992f9bb59bf2a457eb778e42582c85b4.tar.gz |
Merge pull request #925 from dtolnay/cxxstringreserve
Expose reserve on CxxString
-rw-r--r-- | src/cxx.cc | 5 | ||||
-rw-r--r-- | src/cxx_string.rs | 30 |
2 files changed, 35 insertions, 0 deletions
@@ -24,6 +24,11 @@ std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept { void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); } +void cxxbridge1$cxx_string$reserve_total(std::string &s, + size_t new_cap) noexcept { + s.reserve(new_cap); +} + void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr, std::size_t len) noexcept { s.append(reinterpret_cast<const char *>(ptr), len); diff --git a/src/cxx_string.rs b/src/cxx_string.rs index cdd77db5..626c2c85 100644 --- a/src/cxx_string.rs +++ b/src/cxx_string.rs @@ -21,6 +21,8 @@ extern "C" { fn string_length(this: &CxxString) -> usize; #[link_name = "cxxbridge1$cxx_string$clear"] fn string_clear(this: Pin<&mut CxxString>); + #[link_name = "cxxbridge1$cxx_string$reserve_total"] + fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize); #[link_name = "cxxbridge1$cxx_string$push"] fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize); } @@ -161,6 +163,34 @@ impl CxxString { unsafe { string_clear(self) } } + /// Ensures that this string's capacity is at least `additional` bytes + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` bytes if it + /// chooses, to amortize the cost of frequent reallocations. + /// + /// **The meaning of the argument is not the same as + /// [std::string::reserve][reserve] in C++.** The C++ standard library and + /// Rust standard library both have a `reserve` method on strings, but in + /// C++ code the argument always refers to total capacity, whereas in Rust + /// code it always refers to additional capacity. This API on `CxxString` + /// follows the Rust convention, the same way that for the length accessor + /// we use the Rust conventional `len()` naming and not C++ `size()` or + /// `length()`. + /// + /// # Panics + /// + /// Panics if the new capacity overflows usize. + /// + /// [reserve]: https://en.cppreference.com/w/cpp/string/basic_string/reserve + pub fn reserve(self: Pin<&mut Self>, additional: usize) { + let new_cap = self + .len() + .checked_add(additional) + .expect("CxxString capacity overflow"); + unsafe { string_reserve_total(self, new_cap) } + } + /// Appends a given string slice onto the end of this C++ string. pub fn push_str(self: Pin<&mut Self>, s: &str) { self.push_bytes(s.as_bytes()); |