aboutsummaryrefslogtreecommitdiff
path: root/src/cxx_string.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cxx_string.rs')
-rw-r--r--src/cxx_string.rs56
1 files changed, 53 insertions, 3 deletions
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index dce7053d..626c2c85 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -19,6 +19,10 @@ extern "C" {
fn string_data(this: &CxxString) -> *const u8;
#[link_name = "cxxbridge1$cxx_string$length"]
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);
}
@@ -144,6 +148,49 @@ impl CxxString {
String::from_utf8_lossy(self.as_bytes())
}
+ /// Removes all characters from the string.
+ ///
+ /// Matches the behavior of C++ [std::string::clear][clear].
+ ///
+ /// Note: **unlike** the guarantee of Rust's `std::string::String::clear`,
+ /// the C++ standard does not require that capacity is unchanged by this
+ /// operation. In practice existing implementations do not change the
+ /// capacity but all pointers, references, and iterators into the string
+ /// contents are nevertheless invalidated.
+ ///
+ /// [clear]: https://en.cppreference.com/w/cpp/string/basic_string/clear
+ pub fn clear(self: Pin<&mut Self>) {
+ 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());
@@ -213,6 +260,7 @@ pub struct StackString {
space: MaybeUninit<[usize; 8]>,
}
+#[allow(missing_docs)]
impl StackString {
pub fn new() -> Self {
StackString {
@@ -222,9 +270,11 @@ impl StackString {
pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
let value = value.as_ref();
- let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
- string_init(this, value.as_ptr(), value.len());
- Pin::new_unchecked(&mut *this.as_mut_ptr())
+ unsafe {
+ let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
+ string_init(this, value.as_ptr(), value.len());
+ Pin::new_unchecked(&mut *this.as_mut_ptr())
+ }
}
}