Skip to content

Commit

Permalink
Rollup merge of rust-lang#124593 - GKFX:cstr-literals-in-api-docs, r=…
Browse files Browse the repository at this point in the history
…workingjubilee

Describe and use CStr literals in CStr and CString docs

Mention CStr literals in the description of both types, and use them in some of the code samples for CStr. This is intended to make C string literals more discoverable.

Additionally, I don't think the orange "This example is not tested" warnings are very encouraging, so I have made the examples on `CStr` build.
  • Loading branch information
fmease authored May 3, 2024
2 parents 79734f1 + e610a52 commit 60e983e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
14 changes: 5 additions & 9 deletions library/alloc/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use crate::sync::Arc;
/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
/// example, you can build a `CString` straight out of a [`String`] or
/// a <code>&[str]</code>, since both implement that trait).
/// You can create a `CString` from a literal with `CString::from(c"Text")`.
///
/// The [`CString::new`] method will actually check that the provided <code>&[[u8]]</code>
/// does not have 0 bytes in the middle, and return an error if it
Expand Down Expand Up @@ -1069,27 +1070,22 @@ impl CStr {
///
/// # Examples
///
/// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
/// Calling `to_string_lossy` on a `CStr` containing valid UTF-8. The leading
/// `c` on the string literal denotes a `CStr`.
///
/// ```
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let cstr = CStr::from_bytes_with_nul(b"Hello World\0")
/// .expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));
/// assert_eq!(c"Hello World".to_string_lossy(), Cow::Borrowed("Hello World"));
/// ```
///
/// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
///
/// ```
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
/// .expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(
/// cstr.to_string_lossy(),
/// c"Hello \xF0\x90\x80World".to_string_lossy(),
/// Cow::Owned(String::from("Hello �World")) as Cow<'_, str>
/// );
/// ```
Expand Down
35 changes: 23 additions & 12 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,32 @@ use crate::str;
///
/// This type represents a borrowed reference to a nul-terminated
/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
/// slice, or unsafely from a raw `*const c_char`. It can then be
/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
/// into an owned `CString`.
/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a
/// literal in the form `c"Hello world"`.
///
/// The `CStr` can then be converted to a Rust <code>&[str]</code> by performing
/// UTF-8 validation, or into an owned `CString`.
///
/// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
/// in each pair are borrowed references; the latter are owned
/// strings.
///
/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)`
/// notwithstanding) and is not recommended to be placed in the signatures of FFI functions.
/// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor
/// to provide a safe interface to other consumers.
/// notwithstanding) and should not be placed in the signatures of FFI functions.
/// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe
/// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string:
///
/// ```ignore (extern-declaration)
/// ```
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// # #[cfg(any())] // Extern functions are awkward in doc comments - fake it instead
/// extern "C" { fn my_string() -> *const c_char; }
/// # unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() }
///
/// unsafe {
/// let slice = CStr::from_ptr(my_string());
Expand All @@ -54,12 +58,14 @@ use crate::str;
///
/// Passing a Rust-originating C string:
///
/// ```ignore (extern-declaration)
/// ```
/// use std::ffi::{CString, CStr};
/// use std::os::raw::c_char;
///
/// fn work(data: &CStr) {
/// # #[cfg(any())] // Extern functions are awkward in doc comments - fake it instead
/// extern "C" { fn work_with(data: *const c_char); }
/// # unsafe extern "C" fn work_with(s: *const c_char) {}
///
/// unsafe { work_with(data.as_ptr()) }
/// }
Expand All @@ -70,11 +76,13 @@ use crate::str;
///
/// Converting a foreign C string into a Rust `String`:
///
/// ```ignore (extern-declaration)
/// ```
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// # #[cfg(any())] // Extern functions are awkward in doc comments - fake it instead
/// extern "C" { fn my_string() -> *const c_char; }
/// # unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() }
///
/// fn my_string_safe() -> String {
/// let cstr = unsafe { CStr::from_ptr(my_string()) };
Expand Down Expand Up @@ -241,11 +249,11 @@ impl CStr {
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// ```
/// use std::ffi::{c_char, CStr};
///
/// extern "C" {
/// fn my_string() -> *const c_char;
/// fn my_string() -> *const c_char {
/// c"hello".as_ptr()
/// }
///
/// unsafe {
Expand All @@ -264,6 +272,8 @@ impl CStr {
/// BYTES.as_ptr().cast()
/// };
/// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
///
/// assert_eq!(c"Hello, world!", HELLO);
/// ```
///
/// [valid]: core::ptr#safety
Expand Down Expand Up @@ -549,6 +559,7 @@ impl CStr {
///
/// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
/// assert!(empty_cstr.is_empty());
/// assert!(c"".is_empty());
/// # Ok(())
/// # }
/// ```
Expand Down

0 comments on commit 60e983e

Please sign in to comment.