133d722a9Sopenharmony_ciuse crate::actually_private::Private;
233d722a9Sopenharmony_ciuse crate::lossy;
333d722a9Sopenharmony_ci#[cfg(feature = "alloc")]
433d722a9Sopenharmony_ciuse alloc::borrow::Cow;
533d722a9Sopenharmony_ci#[cfg(feature = "alloc")]
633d722a9Sopenharmony_ciuse alloc::string::String;
733d722a9Sopenharmony_ciuse core::cmp::Ordering;
833d722a9Sopenharmony_ciuse core::fmt::{self, Debug, Display};
933d722a9Sopenharmony_ciuse core::hash::{Hash, Hasher};
1033d722a9Sopenharmony_ciuse core::marker::{PhantomData, PhantomPinned};
1133d722a9Sopenharmony_ciuse core::mem::MaybeUninit;
1233d722a9Sopenharmony_ciuse core::pin::Pin;
1333d722a9Sopenharmony_ciuse core::slice;
1433d722a9Sopenharmony_ciuse core::str::{self, Utf8Error};
1533d722a9Sopenharmony_ci
1633d722a9Sopenharmony_ciextern "C" {
1733d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$init"]
1833d722a9Sopenharmony_ci    fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
1933d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$destroy"]
2033d722a9Sopenharmony_ci    fn string_destroy(this: &mut MaybeUninit<CxxString>);
2133d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$data"]
2233d722a9Sopenharmony_ci    fn string_data(this: &CxxString) -> *const u8;
2333d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$length"]
2433d722a9Sopenharmony_ci    fn string_length(this: &CxxString) -> usize;
2533d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$clear"]
2633d722a9Sopenharmony_ci    fn string_clear(this: Pin<&mut CxxString>);
2733d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$reserve_total"]
2833d722a9Sopenharmony_ci    fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize);
2933d722a9Sopenharmony_ci    #[link_name = "cxxbridge1$cxx_string$push"]
3033d722a9Sopenharmony_ci    fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
3133d722a9Sopenharmony_ci}
3233d722a9Sopenharmony_ci
3333d722a9Sopenharmony_ci/// Binding to C++ `std::string`.
3433d722a9Sopenharmony_ci///
3533d722a9Sopenharmony_ci/// # Invariants
3633d722a9Sopenharmony_ci///
3733d722a9Sopenharmony_ci/// As an invariant of this API and the static analysis of the cxx::bridge
3833d722a9Sopenharmony_ci/// macro, in Rust code we can never obtain a `CxxString` by value. C++'s string
3933d722a9Sopenharmony_ci/// requires a move constructor and may hold internal pointers, which is not
4033d722a9Sopenharmony_ci/// compatible with Rust's move behavior. Instead in Rust code we will only ever
4133d722a9Sopenharmony_ci/// look at a CxxString through a reference or smart pointer, as in `&CxxString`
4233d722a9Sopenharmony_ci/// or `UniquePtr<CxxString>`.
4333d722a9Sopenharmony_ci#[repr(C)]
4433d722a9Sopenharmony_cipub struct CxxString {
4533d722a9Sopenharmony_ci    _private: [u8; 0],
4633d722a9Sopenharmony_ci    _pinned: PhantomData<PhantomPinned>,
4733d722a9Sopenharmony_ci}
4833d722a9Sopenharmony_ci
4933d722a9Sopenharmony_ci/// Construct a C++ std::string on the Rust stack.
5033d722a9Sopenharmony_ci///
5133d722a9Sopenharmony_ci/// # Syntax
5233d722a9Sopenharmony_ci///
5333d722a9Sopenharmony_ci/// In statement position:
5433d722a9Sopenharmony_ci///
5533d722a9Sopenharmony_ci/// ```
5633d722a9Sopenharmony_ci/// # use cxx::let_cxx_string;
5733d722a9Sopenharmony_ci/// # let expression = "";
5833d722a9Sopenharmony_ci/// let_cxx_string!(var = expression);
5933d722a9Sopenharmony_ci/// ```
6033d722a9Sopenharmony_ci///
6133d722a9Sopenharmony_ci/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
6233d722a9Sopenharmony_ci/// it will be a string literal, but for example `&[u8]` and `String` would work
6333d722a9Sopenharmony_ci/// as well.
6433d722a9Sopenharmony_ci///
6533d722a9Sopenharmony_ci/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
6633d722a9Sopenharmony_ci/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
6733d722a9Sopenharmony_ci///
6833d722a9Sopenharmony_ci/// # Example
6933d722a9Sopenharmony_ci///
7033d722a9Sopenharmony_ci/// ```
7133d722a9Sopenharmony_ci/// use cxx::{let_cxx_string, CxxString};
7233d722a9Sopenharmony_ci///
7333d722a9Sopenharmony_ci/// fn f(s: &CxxString) {/* ... */}
7433d722a9Sopenharmony_ci///
7533d722a9Sopenharmony_ci/// fn main() {
7633d722a9Sopenharmony_ci///     let_cxx_string!(s = "example");
7733d722a9Sopenharmony_ci///     f(&s);
7833d722a9Sopenharmony_ci/// }
7933d722a9Sopenharmony_ci/// ```
8033d722a9Sopenharmony_ci#[macro_export]
8133d722a9Sopenharmony_cimacro_rules! let_cxx_string {
8233d722a9Sopenharmony_ci    ($var:ident = $value:expr $(,)?) => {
8333d722a9Sopenharmony_ci        let mut cxx_stack_string = $crate::private::StackString::new();
8433d722a9Sopenharmony_ci        #[allow(unused_mut, unused_unsafe)]
8533d722a9Sopenharmony_ci        let mut $var = match $value {
8633d722a9Sopenharmony_ci            let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) },
8733d722a9Sopenharmony_ci        };
8833d722a9Sopenharmony_ci    };
8933d722a9Sopenharmony_ci}
9033d722a9Sopenharmony_ci
9133d722a9Sopenharmony_ciimpl CxxString {
9233d722a9Sopenharmony_ci    /// `CxxString` is not constructible via `new`. Instead, use the
9333d722a9Sopenharmony_ci    /// [`let_cxx_string!`] macro.
9433d722a9Sopenharmony_ci    pub fn new<T: Private>() -> Self {
9533d722a9Sopenharmony_ci        unreachable!()
9633d722a9Sopenharmony_ci    }
9733d722a9Sopenharmony_ci
9833d722a9Sopenharmony_ci    /// Returns the length of the string in bytes.
9933d722a9Sopenharmony_ci    ///
10033d722a9Sopenharmony_ci    /// Matches the behavior of C++ [std::string::size][size].
10133d722a9Sopenharmony_ci    ///
10233d722a9Sopenharmony_ci    /// [size]: https://en.cppreference.com/w/cpp/string/basic_string/size
10333d722a9Sopenharmony_ci    pub fn len(&self) -> usize {
10433d722a9Sopenharmony_ci        unsafe { string_length(self) }
10533d722a9Sopenharmony_ci    }
10633d722a9Sopenharmony_ci
10733d722a9Sopenharmony_ci    /// Returns true if `self` has a length of zero bytes.
10833d722a9Sopenharmony_ci    ///
10933d722a9Sopenharmony_ci    /// Matches the behavior of C++ [std::string::empty][empty].
11033d722a9Sopenharmony_ci    ///
11133d722a9Sopenharmony_ci    /// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty
11233d722a9Sopenharmony_ci    pub fn is_empty(&self) -> bool {
11333d722a9Sopenharmony_ci        self.len() == 0
11433d722a9Sopenharmony_ci    }
11533d722a9Sopenharmony_ci
11633d722a9Sopenharmony_ci    /// Returns a byte slice of this string's contents.
11733d722a9Sopenharmony_ci    pub fn as_bytes(&self) -> &[u8] {
11833d722a9Sopenharmony_ci        let data = self.as_ptr();
11933d722a9Sopenharmony_ci        let len = self.len();
12033d722a9Sopenharmony_ci        unsafe { slice::from_raw_parts(data, len) }
12133d722a9Sopenharmony_ci    }
12233d722a9Sopenharmony_ci
12333d722a9Sopenharmony_ci    /// Produces a pointer to the first character of the string.
12433d722a9Sopenharmony_ci    ///
12533d722a9Sopenharmony_ci    /// Matches the behavior of C++ [std::string::data][data].
12633d722a9Sopenharmony_ci    ///
12733d722a9Sopenharmony_ci    /// Note that the return type may look like `const char *` but is not a
12833d722a9Sopenharmony_ci    /// `const char *` in the typical C sense, as C++ strings may contain
12933d722a9Sopenharmony_ci    /// internal null bytes. As such, the returned pointer only makes sense as a
13033d722a9Sopenharmony_ci    /// string in combination with the length returned by [`len()`][len].
13133d722a9Sopenharmony_ci    ///
13233d722a9Sopenharmony_ci    /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data
13333d722a9Sopenharmony_ci    /// [len]: #method.len
13433d722a9Sopenharmony_ci    pub fn as_ptr(&self) -> *const u8 {
13533d722a9Sopenharmony_ci        unsafe { string_data(self) }
13633d722a9Sopenharmony_ci    }
13733d722a9Sopenharmony_ci
13833d722a9Sopenharmony_ci    /// Validates that the C++ string contains UTF-8 data and produces a view of
13933d722a9Sopenharmony_ci    /// it as a Rust &amp;str, otherwise an error.
14033d722a9Sopenharmony_ci    pub fn to_str(&self) -> Result<&str, Utf8Error> {
14133d722a9Sopenharmony_ci        str::from_utf8(self.as_bytes())
14233d722a9Sopenharmony_ci    }
14333d722a9Sopenharmony_ci
14433d722a9Sopenharmony_ci    /// If the contents of the C++ string are valid UTF-8, this function returns
14533d722a9Sopenharmony_ci    /// a view as a Cow::Borrowed &amp;str. Otherwise replaces any invalid UTF-8
14633d722a9Sopenharmony_ci    /// sequences with the U+FFFD [replacement character] and returns a
14733d722a9Sopenharmony_ci    /// Cow::Owned String.
14833d722a9Sopenharmony_ci    ///
14933d722a9Sopenharmony_ci    /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
15033d722a9Sopenharmony_ci    #[cfg(feature = "alloc")]
15133d722a9Sopenharmony_ci    #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
15233d722a9Sopenharmony_ci    pub fn to_string_lossy(&self) -> Cow<str> {
15333d722a9Sopenharmony_ci        String::from_utf8_lossy(self.as_bytes())
15433d722a9Sopenharmony_ci    }
15533d722a9Sopenharmony_ci
15633d722a9Sopenharmony_ci    /// Removes all characters from the string.
15733d722a9Sopenharmony_ci    ///
15833d722a9Sopenharmony_ci    /// Matches the behavior of C++ [std::string::clear][clear].
15933d722a9Sopenharmony_ci    ///
16033d722a9Sopenharmony_ci    /// Note: **unlike** the guarantee of Rust's `std::string::String::clear`,
16133d722a9Sopenharmony_ci    /// the C++ standard does not require that capacity is unchanged by this
16233d722a9Sopenharmony_ci    /// operation. In practice existing implementations do not change the
16333d722a9Sopenharmony_ci    /// capacity but all pointers, references, and iterators into the string
16433d722a9Sopenharmony_ci    /// contents are nevertheless invalidated.
16533d722a9Sopenharmony_ci    ///
16633d722a9Sopenharmony_ci    /// [clear]: https://en.cppreference.com/w/cpp/string/basic_string/clear
16733d722a9Sopenharmony_ci    pub fn clear(self: Pin<&mut Self>) {
16833d722a9Sopenharmony_ci        unsafe { string_clear(self) }
16933d722a9Sopenharmony_ci    }
17033d722a9Sopenharmony_ci
17133d722a9Sopenharmony_ci    /// Ensures that this string's capacity is at least `additional` bytes
17233d722a9Sopenharmony_ci    /// larger than its length.
17333d722a9Sopenharmony_ci    ///
17433d722a9Sopenharmony_ci    /// The capacity may be increased by more than `additional` bytes if it
17533d722a9Sopenharmony_ci    /// chooses, to amortize the cost of frequent reallocations.
17633d722a9Sopenharmony_ci    ///
17733d722a9Sopenharmony_ci    /// **The meaning of the argument is not the same as
17833d722a9Sopenharmony_ci    /// [std::string::reserve][reserve] in C++.** The C++ standard library and
17933d722a9Sopenharmony_ci    /// Rust standard library both have a `reserve` method on strings, but in
18033d722a9Sopenharmony_ci    /// C++ code the argument always refers to total capacity, whereas in Rust
18133d722a9Sopenharmony_ci    /// code it always refers to additional capacity. This API on `CxxString`
18233d722a9Sopenharmony_ci    /// follows the Rust convention, the same way that for the length accessor
18333d722a9Sopenharmony_ci    /// we use the Rust conventional `len()` naming and not C++ `size()` or
18433d722a9Sopenharmony_ci    /// `length()`.
18533d722a9Sopenharmony_ci    ///
18633d722a9Sopenharmony_ci    /// # Panics
18733d722a9Sopenharmony_ci    ///
18833d722a9Sopenharmony_ci    /// Panics if the new capacity overflows usize.
18933d722a9Sopenharmony_ci    ///
19033d722a9Sopenharmony_ci    /// [reserve]: https://en.cppreference.com/w/cpp/string/basic_string/reserve
19133d722a9Sopenharmony_ci    pub fn reserve(self: Pin<&mut Self>, additional: usize) {
19233d722a9Sopenharmony_ci        let new_cap = self
19333d722a9Sopenharmony_ci            .len()
19433d722a9Sopenharmony_ci            .checked_add(additional)
19533d722a9Sopenharmony_ci            .expect("CxxString capacity overflow");
19633d722a9Sopenharmony_ci        unsafe { string_reserve_total(self, new_cap) }
19733d722a9Sopenharmony_ci    }
19833d722a9Sopenharmony_ci
19933d722a9Sopenharmony_ci    /// Appends a given string slice onto the end of this C++ string.
20033d722a9Sopenharmony_ci    pub fn push_str(self: Pin<&mut Self>, s: &str) {
20133d722a9Sopenharmony_ci        self.push_bytes(s.as_bytes());
20233d722a9Sopenharmony_ci    }
20333d722a9Sopenharmony_ci
20433d722a9Sopenharmony_ci    /// Appends arbitrary bytes onto the end of this C++ string.
20533d722a9Sopenharmony_ci    pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
20633d722a9Sopenharmony_ci        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
20733d722a9Sopenharmony_ci    }
20833d722a9Sopenharmony_ci}
20933d722a9Sopenharmony_ci
21033d722a9Sopenharmony_ciimpl Display for CxxString {
21133d722a9Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21233d722a9Sopenharmony_ci        lossy::display(self.as_bytes(), f)
21333d722a9Sopenharmony_ci    }
21433d722a9Sopenharmony_ci}
21533d722a9Sopenharmony_ci
21633d722a9Sopenharmony_ciimpl Debug for CxxString {
21733d722a9Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21833d722a9Sopenharmony_ci        lossy::debug(self.as_bytes(), f)
21933d722a9Sopenharmony_ci    }
22033d722a9Sopenharmony_ci}
22133d722a9Sopenharmony_ci
22233d722a9Sopenharmony_ciimpl PartialEq for CxxString {
22333d722a9Sopenharmony_ci    fn eq(&self, other: &Self) -> bool {
22433d722a9Sopenharmony_ci        self.as_bytes() == other.as_bytes()
22533d722a9Sopenharmony_ci    }
22633d722a9Sopenharmony_ci}
22733d722a9Sopenharmony_ci
22833d722a9Sopenharmony_ciimpl PartialEq<CxxString> for str {
22933d722a9Sopenharmony_ci    fn eq(&self, other: &CxxString) -> bool {
23033d722a9Sopenharmony_ci        self.as_bytes() == other.as_bytes()
23133d722a9Sopenharmony_ci    }
23233d722a9Sopenharmony_ci}
23333d722a9Sopenharmony_ci
23433d722a9Sopenharmony_ciimpl PartialEq<str> for CxxString {
23533d722a9Sopenharmony_ci    fn eq(&self, other: &str) -> bool {
23633d722a9Sopenharmony_ci        self.as_bytes() == other.as_bytes()
23733d722a9Sopenharmony_ci    }
23833d722a9Sopenharmony_ci}
23933d722a9Sopenharmony_ci
24033d722a9Sopenharmony_ciimpl Eq for CxxString {}
24133d722a9Sopenharmony_ci
24233d722a9Sopenharmony_ciimpl PartialOrd for CxxString {
24333d722a9Sopenharmony_ci    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24433d722a9Sopenharmony_ci        self.as_bytes().partial_cmp(other.as_bytes())
24533d722a9Sopenharmony_ci    }
24633d722a9Sopenharmony_ci}
24733d722a9Sopenharmony_ci
24833d722a9Sopenharmony_ciimpl Ord for CxxString {
24933d722a9Sopenharmony_ci    fn cmp(&self, other: &Self) -> Ordering {
25033d722a9Sopenharmony_ci        self.as_bytes().cmp(other.as_bytes())
25133d722a9Sopenharmony_ci    }
25233d722a9Sopenharmony_ci}
25333d722a9Sopenharmony_ci
25433d722a9Sopenharmony_ciimpl Hash for CxxString {
25533d722a9Sopenharmony_ci    fn hash<H: Hasher>(&self, state: &mut H) {
25633d722a9Sopenharmony_ci        self.as_bytes().hash(state);
25733d722a9Sopenharmony_ci    }
25833d722a9Sopenharmony_ci}
25933d722a9Sopenharmony_ci
26033d722a9Sopenharmony_ciimpl fmt::Write for Pin<&mut CxxString> {
26133d722a9Sopenharmony_ci    fn write_str(&mut self, s: &str) -> fmt::Result {
26233d722a9Sopenharmony_ci        self.as_mut().push_str(s);
26333d722a9Sopenharmony_ci        Ok(())
26433d722a9Sopenharmony_ci    }
26533d722a9Sopenharmony_ci}
26633d722a9Sopenharmony_ci
26733d722a9Sopenharmony_ci#[cfg(feature = "std")]
26833d722a9Sopenharmony_ciimpl std::io::Write for Pin<&mut CxxString> {
26933d722a9Sopenharmony_ci    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
27033d722a9Sopenharmony_ci        self.as_mut().push_bytes(buf);
27133d722a9Sopenharmony_ci        Ok(buf.len())
27233d722a9Sopenharmony_ci    }
27333d722a9Sopenharmony_ci
27433d722a9Sopenharmony_ci    fn flush(&mut self) -> std::io::Result<()> {
27533d722a9Sopenharmony_ci        Ok(())
27633d722a9Sopenharmony_ci    }
27733d722a9Sopenharmony_ci}
27833d722a9Sopenharmony_ci
27933d722a9Sopenharmony_ci#[doc(hidden)]
28033d722a9Sopenharmony_ci#[repr(C)]
28133d722a9Sopenharmony_cipub struct StackString {
28233d722a9Sopenharmony_ci    // Static assertions in cxx.cc validate that this is large enough and
28333d722a9Sopenharmony_ci    // aligned enough.
28433d722a9Sopenharmony_ci    space: MaybeUninit<[usize; 8]>,
28533d722a9Sopenharmony_ci}
28633d722a9Sopenharmony_ci
28733d722a9Sopenharmony_ci#[allow(missing_docs)]
28833d722a9Sopenharmony_ciimpl StackString {
28933d722a9Sopenharmony_ci    pub fn new() -> Self {
29033d722a9Sopenharmony_ci        StackString {
29133d722a9Sopenharmony_ci            space: MaybeUninit::uninit(),
29233d722a9Sopenharmony_ci        }
29333d722a9Sopenharmony_ci    }
29433d722a9Sopenharmony_ci
29533d722a9Sopenharmony_ci    pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
29633d722a9Sopenharmony_ci        let value = value.as_ref();
29733d722a9Sopenharmony_ci        unsafe {
29833d722a9Sopenharmony_ci            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
29933d722a9Sopenharmony_ci            string_init(this, value.as_ptr(), value.len());
30033d722a9Sopenharmony_ci            Pin::new_unchecked(&mut *this.as_mut_ptr())
30133d722a9Sopenharmony_ci        }
30233d722a9Sopenharmony_ci    }
30333d722a9Sopenharmony_ci}
30433d722a9Sopenharmony_ci
30533d722a9Sopenharmony_ciimpl Drop for StackString {
30633d722a9Sopenharmony_ci    fn drop(&mut self) {
30733d722a9Sopenharmony_ci        unsafe {
30833d722a9Sopenharmony_ci            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
30933d722a9Sopenharmony_ci            string_destroy(this);
31033d722a9Sopenharmony_ci        }
31133d722a9Sopenharmony_ci    }
31233d722a9Sopenharmony_ci}
313