Skip to content

Commit

Permalink
Merge pull request torvalds#533 from mdaverde/ml/cstr
Browse files Browse the repository at this point in the history
rust: add `to_str` and `as_str_unchecked` to `CStr`
  • Loading branch information
ojeda authored Oct 28, 2021
2 parents 597bee0 + 813e0c1 commit b9ed1ad
Showing 1 changed file with 69 additions and 0 deletions.
69 changes: 69 additions & 0 deletions rust/kernel/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,46 @@ impl CStr {
pub const fn as_bytes_with_nul(&self) -> &[u8] {
&self.0
}

/// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.
///
/// If the contents of the [`CStr`] are valid UTF-8 data, this
/// function will return the corresponding [`&str`] slice. Otherwise,
/// it will return an error with details of where UTF-8 validation failed.
///
/// # Examples
///
/// ```
/// # use kernel::str::CStr;
/// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// assert_eq!(cstr.to_str(), Ok("foo"));
/// ```
#[inline]
pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
core::str::from_utf8(self.as_bytes())
}

/// Unsafely convert this [`CStr`] into a [`&str`], without checking for
/// valid UTF-8.
///
/// # Safety
///
/// The contents must be valid UTF-8.
///
/// # Examples
///
/// ```
/// # use kernel::c_str;
/// # use kernel::str::CStr;
/// // SAFETY: String literals are guaranteed to be valid UTF-8
/// // by the Rust compiler.
/// let bar = c_str!("ツ");
/// assert_eq!(unsafe { bar.as_str_unchecked() }, "ツ");
/// ```
#[inline]
pub unsafe fn as_str_unchecked(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
}
}

impl AsRef<BStr> for CStr {
Expand Down Expand Up @@ -251,3 +291,32 @@ macro_rules! c_str {
C
}};
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_cstr_to_str() {
let good_bytes = b"\xf0\x9f\xa6\x80\0";
let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
let checked_str = checked_cstr.to_str().unwrap();
assert_eq!(checked_str, "🦀");
}

#[test]
#[should_panic]
fn test_cstr_to_str_panic() {
let bad_bytes = b"\xc3\x28\0";
let checked_cstr = CStr::from_bytes_with_nul(bad_bytes).unwrap();
checked_cstr.to_str().unwrap();
}

#[test]
fn test_cstr_as_str_unchecked() {
let good_bytes = b"\xf0\x9f\x90\xA7\0";
let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
let unchecked_str = unsafe { checked_cstr.as_str_unchecked() };
assert_eq!(unchecked_str, "🐧");
}
}

0 comments on commit b9ed1ad

Please sign in to comment.