Skip to content

Commit

Permalink
rust: str: add conversion from CStr to CString
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Darksonn authored and ojeda committed May 31, 2023
1 parent 4a59081 commit 66bd753
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions rust/kernel/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -199,6 +200,12 @@ impl CStr {
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 {
Expand Down Expand Up @@ -584,6 +591,21 @@ impl Deref for CString {
}
}

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 {
Expand Down

0 comments on commit 66bd753

Please sign in to comment.