diff options
author | Alice Ryhl <aliceryhl@google.com> | 2023-05-03 17:10:16 +0300 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2023-05-31 19:53:10 +0300 |
commit | 66bd7533ef19bf8a3515ce702013aba368f58df3 (patch) | |
tree | 01750da9020ab71d9df5eedf7e4f82a3f794a2ed /rust | |
parent | 4a59081c09cbfe17505baf3db50ebb9b97290bae (diff) | |
download | linux-66bd7533ef19bf8a3515ce702013aba368f58df3.tar.xz |
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>
Diffstat (limited to 'rust')
-rw-r--r-- | rust/kernel/str.rs | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index cd3d2a6cf1fc..c9dd3bf59e34 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, AllocError> { + 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<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 { |