Struct CString

struct CString { ... }

A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the middle.

This type serves the purpose of being able to safely generate a C-compatible string from a Rust byte slice or vector. An instance of this type is a static guarantee that the underlying bytes contain no interior 0 bytes ("nul characters") and that the final byte is 0 ("nul terminator").

CString is to &[CStr] as String is to &str: the former in each pair are owned strings; the latter are borrowed references.

Creating a CString

A CString is created from either a byte slice or a byte vector, or anything that implements [Into]<[Vec]<[u8]>> (for example, you can build a CString straight out of a String or a &str, 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 &[[u8]] does not have 0 bytes in the middle, and return an error if it finds one.

Extracting a raw pointer to the whole C string

CString implements an [as_ptr]CStr::as_ptr method through the Deref trait. This method will give you a *const c_char which you can feed directly to extern functions that expect a nul-terminated string, like C's strdup(). Notice that [as_ptr]CStr::as_ptr returns a read-only pointer; if the C code writes to it, that causes undefined behavior.

Extracting a slice of the whole C string

Alternatively, you can obtain a &[[u8]] slice from a CString with the CString::as_bytes method. Slices produced in this way do not contain the trailing nul terminator. This is useful when you will be calling an extern function that takes a *const u8 argument which is not necessarily nul-terminated, plus another argument with the length of the string — like C's strndup(). You can of course get the slice's length with its [len][slice::len] method.

If you need a &[[u8]] slice with the nul terminator, you can use CString::as_bytes_with_nul instead.

Once you have the kind of slice you need (with or without a nul terminator), you can call the slice's own [as_ptr][slice::as_ptr] method to get a read-only raw pointer to pass to extern functions. See the documentation for that function for a discussion on ensuring the lifetime of the raw pointer.

Examples

# fn main() {
use std::ffi::CString;
use std::os::raw::c_char;

extern "C" {
    fn my_printer(s: *const c_char);
}

// We are certain that our string doesn't have 0 bytes in the middle,
// so we can .expect()
let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
unsafe {
    my_printer(c_to_print.as_ptr());
}
# }

Safety

CString is intended for working with traditional C-style strings (a sequence of non-nul bytes terminated by a single nul byte); the primary use case for these kinds of strings is interoperating with C-like code. Often you will need to transfer ownership to/from that external code. It is strongly recommended that you thoroughly read through the documentation of CString before use, as improper ownership management of CString instances can lead to invalid memory accesses, memory leaks, and other memory errors.

Implementations

impl CString

fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError>

Creates a new C-compatible string from a container of bytes.

This function will consume the provided data and use the underlying bytes to construct a new string, ensuring that there is a trailing 0 byte. This trailing 0 byte will be appended by this function; the provided data should not contain any 0 bytes in it.

Examples

use std::ffi::CString;
use std::os::raw::c_char;

extern "C" { fn puts(s: *const c_char); }

let to_print = CString::new("Hello!").expect("CString::new failed");
unsafe {
    puts(to_print.as_ptr());
}

Errors

This function will return an error if the supplied bytes contain an internal 0 byte. The NulError returned will contain the bytes as well as the position of the nul byte.

unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self

Creates a C-compatible string by consuming a byte vector, without checking for interior 0 bytes.

Trailing 0 byte will be appended by this function.

This method is equivalent to CString::new except that no runtime assertion is made that v contains no 0 bytes, and it requires an actual byte vector, not anything that can be converted to one with Into.

Examples

use std::ffi::CString;

let raw = b"foo".to_vec();
unsafe {
    let c_string = CString::from_vec_unchecked(raw);
}
unsafe fn from_raw(ptr: *mut c_char) -> CString

Retakes ownership of a CString that was transferred to C via CString::into_raw.

Additionally, the length of the string will be recalculated from the pointer.

Safety

This should only ever be called with a pointer that was earlier obtained by calling CString::into_raw, and the memory it points to must not be accessed through any other pointer during the lifetime of reconstructed CString. Other usage (e.g., trying to take ownership of a string that was allocated by foreign code) is likely to lead to undefined behavior or allocator corruption.

This function does not validate ownership of the raw pointer's memory. A double-free may occur if the function is called twice on the same raw pointer. Additionally, the caller must ensure the pointer is not dangling.

It should be noted that the length isn't just "recomputed," but that the recomputed length must match the original length from the CString::into_raw call. This means the CString::into_raw/from_raw methods should not be used when passing the string to C functions that can modify the string's length.

Note: If you need to borrow a string that was allocated by foreign code, use CStr. If you need to take ownership of a string that was allocated by foreign code, you will need to make your own provisions for freeing it appropriately, likely with the foreign code's API to do that.

Examples

Creates a CString, pass ownership to an extern function (via raw pointer), then retake ownership with from_raw:

use std::ffi::CString;
use std::os::raw::c_char;

extern "C" {
    fn some_extern_function(s: *mut c_char);
}

let c_string = CString::from(c"Hello!");
let raw = c_string.into_raw();
unsafe {
    some_extern_function(raw);
    let c_string = CString::from_raw(raw);
}
fn into_raw(self: Self) -> *mut c_char

Consumes the CString and transfers ownership of the string to a C caller.

The pointer which this function returns must be returned to Rust and reconstituted using CString::from_raw to be properly deallocated. Specifically, one should not use the standard C free() function to deallocate this string.

Failure to call CString::from_raw will lead to a memory leak.

The C side must not modify the length of the string (by writing a nul byte somewhere inside the string or removing the final one) before it makes it back into Rust using CString::from_raw. See the safety section in CString::from_raw.

Examples

use std::ffi::CString;

let c_string = CString::from(c"foo");

let ptr = c_string.into_raw();

unsafe {
    assert_eq!(b'f', *ptr as u8);
    assert_eq!(b'o', *ptr.add(1) as u8);
    assert_eq!(b'o', *ptr.add(2) as u8);
    assert_eq!(b'\0', *ptr.add(3) as u8);

    // retake pointer to free memory
    let _ = CString::from_raw(ptr);
}
fn into_string(self: Self) -> Result<String, IntoStringError>

Converts the CString into a String if it contains valid UTF-8 data.

On failure, ownership of the original CString is returned.

Examples

use std::ffi::CString;

let valid_utf8 = vec![b'f', b'o', b'o'];
let cstring = CString::new(valid_utf8).expect("CString::new failed");
assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");

let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
let cstring = CString::new(invalid_utf8).expect("CString::new failed");
let err = cstring.into_string().err().expect("into_string().err() failed");
assert_eq!(err.utf8_error().valid_up_to(), 1);
fn into_bytes(self: Self) -> Vec<u8>

Consumes the CString and returns the underlying byte buffer.

The returned buffer does not contain the trailing nul terminator, and it is guaranteed to not have any interior nul bytes.

Examples

use std::ffi::CString;

let c_string = CString::from(c"foo");
let bytes = c_string.into_bytes();
assert_eq!(bytes, vec![b'f', b'o', b'o']);
fn into_bytes_with_nul(self: Self) -> Vec<u8>

Equivalent to [CString::into_bytes()] except that the returned vector includes the trailing nul terminator.

Examples

use std::ffi::CString;

let c_string = CString::from(c"foo");
let bytes = c_string.into_bytes_with_nul();
assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
fn as_bytes(self: &Self) -> &[u8]

Returns the contents of this CString as a slice of bytes.

The returned slice does not contain the trailing nul terminator, and it is guaranteed to not have any interior nul bytes. If you need the nul terminator, use CString::as_bytes_with_nul instead.

Examples

use std::ffi::CString;

let c_string = CString::from(c"foo");
let bytes = c_string.as_bytes();
assert_eq!(bytes, &[b'f', b'o', b'o']);
fn as_bytes_with_nul(self: &Self) -> &[u8]

Equivalent to [CString::as_bytes()] except that the returned slice includes the trailing nul terminator.

Examples

use std::ffi::CString;

let c_string = CString::from(c"foo");
let bytes = c_string.as_bytes_with_nul();
assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
fn as_c_str(self: &Self) -> &CStr

Extracts a CStr slice containing the entire string.

Examples

use std::ffi::{CString, CStr};

let c_string = CString::from(c"foo");
let cstr = c_string.as_c_str();
assert_eq!(cstr,
           CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
fn into_boxed_c_str(self: Self) -> Box<CStr>

Converts this CString into a boxed CStr.

Examples

let c_string = c"foo".to_owned();
let boxed = c_string.into_boxed_c_str();
assert_eq!(boxed.to_bytes_with_nul(), b"foo\0");
unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self

Converts a [Vec]<[u8]> to a CString without checking the invariants on the given Vec.

Safety

The given Vec must have one nul byte as its last element. This means it cannot be empty nor have any other nul byte anywhere else.

Example

use std::ffi::CString;
assert_eq!(
    unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
    unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
);
fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError>

Attempts to convert a [Vec]<[u8]> to a CString.

Runtime checks are present to ensure there is only one nul byte in the Vec, its last element.

Errors

If a nul byte is present and not the last element or no nul bytes is present, an error will be returned.

Examples

A successful conversion will produce the same result as CString::new when called without the ending nul byte.

use std::ffi::CString;
assert_eq!(
    CString::from_vec_with_nul(b"abc\0".to_vec())
        .expect("CString::from_vec_with_nul failed"),
    c"abc".to_owned()
);

An incorrectly formatted Vec will produce an error.

use std::ffi::{CString, FromVecWithNulError};
// Interior nul byte
let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
// No nul byte
let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();

impl AsRef for CString

fn as_ref(self: &Self) -> &CStr

impl Borrow for CString

fn borrow(self: &Self) -> &CStr

impl Clone for CString

fn clone(self: &Self) -> CString

impl Debug for CString

fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result

impl Default for CString

fn default() -> CString

Creates an empty CString.

impl Deref for CString

fn deref(self: &Self) -> &CStr

impl Drop for CString

fn drop(self: &mut Self)

impl Eq for CString

impl Freeze for CString

impl From for CString

fn from(v: Vec<NonZero<u8>>) -> CString

Converts a [Vec]<[NonZero]<[u8]>> into a CString without copying nor checking for inner nul bytes.

impl From for CString

fn from(s: &CStr) -> CString

Converts a &[CStr] into a CString by copying the contents into a new allocation.

impl From for CString

fn from(s: Box<CStr>) -> CString

Converts a [Box]<[CStr]> into a CString without copying or allocating.

impl FromStr for CString

fn from_str(s: &str) -> Result<Self, <Self as >::Err>

Converts a string s into a CString.

This method is equivalent to CString::new.

impl Hash for CString

fn hash<__H: $crate::hash::Hasher>(self: &Self, state: &mut __H)

impl Index for CString

fn index(self: &Self, _index: ops::RangeFull) -> &CStr

impl Ord for CString

fn cmp(self: &Self, other: &CString) -> $crate::cmp::Ordering

impl PartialEq for CString

fn eq(self: &Self, other: &CStr) -> bool
fn ne(self: &Self, other: &CStr) -> bool

impl PartialEq for CString

fn eq(self: &Self, other: &Cow<'_, CStr>) -> bool
fn ne(self: &Self, other: &Cow<'_, CStr>) -> bool

impl PartialEq for CString

fn eq(self: &Self, other: &CString) -> bool

impl PartialEq for CString

fn eq(self: &Self, other: &&CStr) -> bool
fn ne(self: &Self, other: &&CStr) -> bool

impl PartialOrd for CString

fn partial_cmp(self: &Self, other: &CString) -> $crate::option::Option<$crate::cmp::Ordering>

impl RefUnwindSafe for CString

impl Send for CString

impl StructuralPartialEq for CString

impl Sync for CString

impl Unpin for CString

impl UnwindSafe for CString

impl<'a> From for CString

fn from(s: Cow<'a, CStr>) -> Self

Converts a Cow<'a, CStr> into a CString, by copying the contents if they are borrowed.

impl<P, T> Receiver for CString

impl<T> Any for CString

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for CString

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for CString

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for CString

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> From for CString

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for CString

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T, U> Into for CString

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for CString

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for CString

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>