Describe and use CStr literals in CStr and CString docs

This commit is contained in:
George Bateman 2024-05-01 19:28:45 +01:00
parent 20aa2d81e3
commit e610a52a62
No known key found for this signature in database
GPG Key ID: C417AA9C4039EFCF
2 changed files with 28 additions and 21 deletions

View File

@ -41,6 +41,7 @@
/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for /// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
/// example, you can build a `CString` straight out of a [`String`] or /// example, you can build a `CString` straight out of a [`String`] or
/// a <code>&[str]</code>, since both implement that trait). /// 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> /// 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 /// does not have 0 bytes in the middle, and return an error if it
@ -1069,27 +1070,22 @@ impl CStr {
/// ///
/// # Examples /// # 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::borrow::Cow;
/// use std::ffi::CStr;
/// ///
/// let cstr = CStr::from_bytes_with_nul(b"Hello World\0") /// assert_eq!(c"Hello World".to_string_lossy(), Cow::Borrowed("Hello World"));
/// .expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));
/// ``` /// ```
/// ///
/// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
/// ///
/// ``` /// ```
/// use std::borrow::Cow; /// 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!( /// assert_eq!(
/// cstr.to_string_lossy(), /// c"Hello \xF0\x90\x80World".to_string_lossy(),
/// Cow::Owned(String::from("Hello <20>World")) as Cow<'_, str> /// Cow::Owned(String::from("Hello <20>World")) as Cow<'_, str>
/// ); /// );
/// ``` /// ```

View File

@ -23,28 +23,32 @@
/// ///
/// This type represents a borrowed reference to a nul-terminated /// This type represents a borrowed reference to a nul-terminated
/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code> /// 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 /// slice, or unsafely from a raw `*const c_char`. It can be expressed as a
/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or /// literal in the form `c"Hello world"`.
/// into an owned `CString`. ///
/// 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 /// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
/// in each pair are borrowed references; the latter are owned /// in each pair are borrowed references; the latter are owned
/// strings. /// strings.
/// ///
/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)` /// 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. /// notwithstanding) and should not be placed in the signatures of FFI functions.
/// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor /// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe
/// to provide a safe interface to other consumers. /// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers.
/// ///
/// # Examples /// # Examples
/// ///
/// Inspecting a foreign C string: /// Inspecting a foreign C string:
/// ///
/// ```ignore (extern-declaration) /// ```
/// use std::ffi::CStr; /// use std::ffi::CStr;
/// use std::os::raw::c_char; /// 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; } /// extern "C" { fn my_string() -> *const c_char; }
/// # unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() }
/// ///
/// unsafe { /// unsafe {
/// let slice = CStr::from_ptr(my_string()); /// let slice = CStr::from_ptr(my_string());
@ -54,12 +58,14 @@
/// ///
/// Passing a Rust-originating C string: /// Passing a Rust-originating C string:
/// ///
/// ```ignore (extern-declaration) /// ```
/// use std::ffi::{CString, CStr}; /// use std::ffi::{CString, CStr};
/// use std::os::raw::c_char; /// use std::os::raw::c_char;
/// ///
/// fn work(data: &CStr) { /// 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); } /// 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()) } /// unsafe { work_with(data.as_ptr()) }
/// } /// }
@ -70,11 +76,13 @@
/// ///
/// Converting a foreign C string into a Rust `String`: /// Converting a foreign C string into a Rust `String`:
/// ///
/// ```ignore (extern-declaration) /// ```
/// use std::ffi::CStr; /// use std::ffi::CStr;
/// use std::os::raw::c_char; /// 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; } /// 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 { /// fn my_string_safe() -> String {
/// let cstr = unsafe { CStr::from_ptr(my_string()) }; /// let cstr = unsafe { CStr::from_ptr(my_string()) };
@ -241,11 +249,11 @@ impl CStr {
/// ///
/// # Examples /// # Examples
/// ///
/// ```ignore (extern-declaration) /// ```
/// use std::ffi::{c_char, CStr}; /// 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 { /// unsafe {
@ -264,6 +272,8 @@ impl CStr {
/// BYTES.as_ptr().cast() /// BYTES.as_ptr().cast()
/// }; /// };
/// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
///
/// assert_eq!(c"Hello, world!", HELLO);
/// ``` /// ```
/// ///
/// [valid]: core::ptr#safety /// [valid]: core::ptr#safety
@ -549,6 +559,7 @@ pub const fn count_bytes(&self) -> usize {
/// ///
/// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
/// assert!(empty_cstr.is_empty()); /// assert!(empty_cstr.is_empty());
/// assert!(c"".is_empty());
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```