rust: str: add conversion from CStr to CString

These methods can be used to copy the data in a temporary c string into
a separate allocation, so that it can be accessed later even if the
original is deallocated.

The API in this change mirrors the standard library API for the `&str`
and `String` types. The `ToOwned` trait is not implemented because it
assumes that allocations are infallible.

Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>
Link: https://lore.kernel.org/r/20230503141016.683634-1-aliceryhl@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Alice Ryhl 2023-05-03 14:10:16 +00:00 committed by Miguel Ojeda
parent 4a59081c09
commit 66bd7533ef

View File

@ -2,6 +2,7 @@
//! String representations.
use alloc::alloc::AllocError;
use alloc::vec::Vec;
use core::fmt::{self, Write};
use core::ops::{self, Deref, Index};
@ -199,6 +200,12 @@ pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
pub unsafe fn as_str_unchecked(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
}
/// Convert this [`CStr`] into a [`CString`] by allocating memory and
/// copying over the string data.
pub fn to_cstring(&self) -> Result<CString, AllocError> {
CString::try_from(self)
}
}
impl fmt::Display for CStr {
@ -584,6 +591,21 @@ fn deref(&self) -> &Self::Target {
}
}
impl<'a> TryFrom<&'a CStr> for CString {
type Error = AllocError;
fn try_from(cstr: &'a CStr) -> Result<CString, AllocError> {
let mut buf = Vec::new();
buf.try_extend_from_slice(cstr.as_bytes_with_nul())
.map_err(|_| AllocError)?;
// INVARIANT: The `CStr` and `CString` types have the same invariants for
// the string data, and we copied it over without changes.
Ok(CString { buf })
}
}
/// A convenience alias for [`core::format_args`].
#[macro_export]
macro_rules! fmt {