From: Alice Ryhl Date: Wed, 3 May 2023 14:10:16 +0000 (+0000) Subject: rust: str: add conversion from `CStr` to `CString` X-Git-Tag: v6.6.7~2622^2~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=66bd7533ef19bf8a3515ce702013aba368f58df3;p=platform%2Fkernel%2Flinux-starfive.git 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 Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg Link: https://lore.kernel.org/r/20230503141016.683634-1-aliceryhl@google.com Signed-off-by: Miguel Ojeda --- diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index cd3d2a6..c9dd3bf 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -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 @@ 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::try_from(self) + } } impl fmt::Display for CStr { @@ -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 { + 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 {