This is a reference for converting between various string and byte types in Rust. The types listed are in the sidebar, and each section shows the conversions to all the other types.

These conversions are not exhaustive of course. For example, if the target type can be inferred you might be able to use .into() instead of an explicit method like .to_string(). Additionally, unsafe conversions are not currently included.

If you spot something that could be improved please file an issue or a pull request in the GitHub repo.

Last updated for Rust 1.76.0.

From &str

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};

pub fn str_to_string(input: &str) -> String {
    input.to_string()
}

pub fn str_to_u8_slice(input: &str) -> &[u8] {
    input.as_bytes()
}

pub fn str_to_u8_vec(input: &str) -> Vec<u8> {
    input.as_bytes().to_vec()
}

pub fn str_to_path(input: &str) -> &Path {
    Path::new(input)
}

pub fn str_to_path_buf(input: &str) -> PathBuf {
    PathBuf::from(input)
}

pub fn str_to_os_str(input: &str) -> &OsStr {
    OsStr::new(input)
}

pub fn str_to_os_string(input: &str) -> OsString {
    OsString::from(input)
}

// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn str_to_c_str(input: &str) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_bytes())
}

// A NulError will be returned if the input contains any nul bytes.
pub fn str_to_c_string(input: &str) -> Result<CString, NulError> {
    CString::new(input)
}

From String

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};

pub fn string_to_str(input: &String) -> &str {
    input.as_str()
}

pub fn string_to_u8_slice(input: &String) -> &[u8] {
    input.as_bytes()
}

pub fn string_to_u8_vec(input: String) -> Vec<u8> {
    input.into_bytes()
}

pub fn string_to_path(input: &String) -> &Path {
    Path::new(input)
}

pub fn string_to_path_buf(input: &String) -> PathBuf {
    PathBuf::from(input)
}

pub fn string_to_os_str(input: &String) -> &OsStr {
    OsStr::new(input)
}

pub fn string_to_os_string(input: String) -> OsString {
    OsString::from(input)
}

// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn string_to_c_str(input: &String) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_bytes())
}

// A NulError will be returned if the input contains any nul bytes.
pub fn string_to_c_string(input: String) -> Result<CString, NulError> {
    CString::new(input)
}

From &[u8]

use std::borrow::Cow;
use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::string::FromUtf8Error;

pub fn u8_slice_to_str(input: &[u8]) -> Result<&str, Utf8Error> {
    std::str::from_utf8(input)
}

pub fn u8_slice_to_string(input: &[u8]) -> Result<String, FromUtf8Error> {
    String::from_utf8(input.to_vec())
}

// This never fails, but invalid UTF-8 sequences will be replaced with
// "�". This returns a `Cow<str>`; call `to_string()` to convert it to
// a `String`.
pub fn u8_slice_to_string_lossy(input: &[u8]) -> Cow<str> {
    String::from_utf8_lossy(input)
}

pub fn u8_slice_to_u8_vec(input: &[u8]) -> Vec<u8> {
    input.to_vec()
}

// This conversion is only allowed on Unix.
pub fn u8_slice_to_path_unix(input: &[u8]) -> &Path {
    Path::new(OsStr::from_bytes(input))
}

// This conversion is only allowed on Unix.
pub fn u8_slice_to_path_buf_unix(input: &[u8]) -> PathBuf {
    PathBuf::from(OsStr::from_bytes(input))
}

// This conversion is only allowed on Unix.
pub fn u8_slice_to_os_str_unix(input: &[u8]) -> &OsStr {
    OsStr::from_bytes(input)
}

// This conversion is only allowed on Unix.
pub fn u8_slice_to_os_string_unix(input: &[u8]) -> OsString {
    OsString::from_vec(input.to_vec())
}

// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn u8_slice_to_c_str(input: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input)
}

// A NulError will be returned if the input contains any nul bytes.
pub fn u8_slice_to_c_string(input: &[u8]) -> Result<CString, NulError> {
    CString::new(input)
}

From Vec<u8>

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::string::FromUtf8Error;

pub fn u8_vec_to_str(input: &Vec<u8>) -> Result<&str, Utf8Error> {
    std::str::from_utf8(input)
}

pub fn u8_vec_to_string(input: Vec<u8>) -> Result<String, FromUtf8Error> {
    String::from_utf8(input)
}

pub fn u8_vec_to_u8_slice(input: &Vec<u8>) -> &[u8] {
    input.as_slice()
}

// This conversion is only allowed on Unix.
pub fn u8_vec_to_path_unix(input: &Vec<u8>) -> &Path {
    Path::new(OsStr::from_bytes(input))
}

// This conversion is only allowed on Unix.
pub fn u8_vec_to_path_buf_unix(input: Vec<u8>) -> PathBuf {
    PathBuf::from(OsString::from_vec(input))
}

// This conversion is only allowed on Unix.
pub fn u8_vec_to_os_str_unix(input: &Vec<u8>) -> &OsStr {
    OsStr::from_bytes(input)
}

// This conversion is only allowed on Unix.
pub fn u8_vec_to_os_string_unix(input: Vec<u8>) -> OsString {
    OsString::from_vec(input)
}

// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn u8_vec_to_c_str(
    input: &Vec<u8>,
) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input)
}

// A NulError will be returned if the input contains any nul bytes.
pub fn u8_vec_to_c_string(input: Vec<u8>) -> Result<CString, NulError> {
    CString::new(input)
}

From &Path

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

// Returns None if the input is not valid UTF-8.
pub fn path_to_str(input: &Path) -> Option<&str> {
    input.to_str()
}

// Returns None if the input is not valid UTF-8.
pub fn path_to_string(input: &Path) -> Option<String> {
    input.to_str().map(|s| s.to_string())
}

// This conversion is only allowed on Unix.
pub fn path_to_u8_slice_unix(input: &Path) -> &[u8] {
    input.as_os_str().as_bytes()
}

// This conversion is only allowed on Unix.
pub fn path_to_u8_vec_unix(input: &Path) -> Vec<u8> {
    input.as_os_str().as_bytes().to_vec()
}

pub fn path_to_path_buf(input: &Path) -> PathBuf {
    input.to_path_buf()
}

pub fn path_to_os_str(input: &Path) -> &OsStr {
    input.as_os_str()
}

pub fn path_to_os_string(input: &Path) -> OsString {
    input.as_os_str().to_os_string()
}

// This conversion is only allowed on Unix.
//
// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn path_to_c_str_unix(
    input: &Path,
) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_os_str().as_bytes())
}

// This conversion is only allowed on Unix.
//
// A NulError will be returned if the input contains any nul bytes.
pub fn path_to_c_string_unix(input: &Path) -> Result<CString, NulError> {
    CString::new(input.as_os_str().as_bytes())
}

From PathBuf

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};

// Returns None if the input is not valid UTF-8.
pub fn path_buf_to_str(input: &PathBuf) -> Option<&str> {
    input.as_path().to_str()
}

// Returns None if the input is not valid UTF-8.
pub fn path_buf_to_string(input: PathBuf) -> Option<String> {
    input.as_path().to_str().map(|s| s.to_string())
}

// This conversion is only allowed on Unix.
pub fn path_buf_to_u8_slice_unix(input: &PathBuf) -> &[u8] {
    input.as_os_str().as_bytes()
}

// This conversion is only allowed on Unix.
pub fn path_buf_to_u8_vec_unix(input: PathBuf) -> Vec<u8> {
    input.into_os_string().into_vec()
}

pub fn path_buf_to_path(input: &PathBuf) -> &Path {
    input.as_path()
}

pub fn path_buf_to_os_str(input: &PathBuf) -> &OsStr {
    input.as_os_str()
}

pub fn path_buf_to_os_string(input: PathBuf) -> OsString {
    input.into_os_string()
}

// This conversion is only allowed on Unix.
//
// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn path_buf_to_c_str_unix(
    input: &PathBuf,
) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_os_str().as_bytes())
}

// This conversion is only allowed on Unix.
//
// A NulError will be returned if the input contains any nul bytes.
pub fn path_buf_to_c_string_unix(input: PathBuf) -> Result<CString, NulError> {
    CString::new(input.into_os_string().into_vec())
}

From &OsStr

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

// Returns None if the input is not valid UTF-8.
pub fn os_str_to_str(input: &OsStr) -> Option<&str> {
    input.to_str()
}

// Returns None if the input is not valid UTF-8.
pub fn os_str_to_string(input: &OsStr) -> Option<String> {
    input.to_str().map(|s| s.to_string())
}

// This conversion is only allowed on Unix.
pub fn os_str_to_u8_slice_unix(input: &OsStr) -> &[u8] {
    input.as_bytes()
}

// This conversion is only allowed on Unix.
pub fn os_str_to_u8_vec_unix(input: &OsStr) -> Vec<u8> {
    input.as_bytes().to_vec()
}

pub fn os_str_to_path(input: &OsStr) -> &Path {
    Path::new(input)
}

pub fn os_str_to_path_buf(input: &OsStr) -> PathBuf {
    PathBuf::from(input)
}

pub fn os_str_to_os_string(input: &OsStr) -> OsString {
    input.to_os_string()
}

// This conversion is only allowed on Unix.
//
// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn os_str_to_c_str_unix(
    input: &OsStr,
) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_bytes())
}

// This conversion is only allowed on Unix.
//
// A NulError will be returned if the input contains any nul bytes.
pub fn os_str_to_c_string_unix(input: &OsStr) -> Result<CString, NulError> {
    CString::new(input.as_bytes())
}

From OsString

use std::ffi::FromBytesWithNulError;
use std::ffi::NulError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};

// Returns None if the input is not valid UTF-8.
pub fn os_string_to_str(input: &OsString) -> Option<&str> {
    input.to_str()
}

pub fn os_string_to_string(input: OsString) -> Result<String, OsString> {
    input.into_string()
}

// This conversion is only allowed on Unix.
pub fn os_string_to_u8_slice_unix(input: &OsString) -> &[u8] {
    input.as_bytes()
}

// This conversion is only allowed on Unix.
pub fn os_string_to_u8_vec_unix(input: OsString) -> Vec<u8> {
    input.into_vec()
}

pub fn os_string_to_path(input: &OsString) -> &Path {
    Path::new(input)
}

pub fn os_string_to_path_buf(input: OsString) -> PathBuf {
    PathBuf::from(input)
}

pub fn os_string_to_os_str(input: &OsString) -> &OsStr {
    input.as_os_str()
}

// This conversion is only allowed on Unix.
//
// A FromBytesWithNulError will be returned if the input is not nul-
// terminated or contains any interior nul bytes. If your input is not nul-
// terminated then a conversion without allocation is not possible, convert
// to a CString instead.
pub fn os_string_to_c_str_unix(
    input: &OsString,
) -> Result<&CStr, FromBytesWithNulError> {
    CStr::from_bytes_with_nul(input.as_bytes())
}

// This conversion is only allowed on Unix.
//
// A NulError will be returned if the input contains any nul bytes.
pub fn os_string_to_c_string_unix(
    input: OsString,
) -> Result<CString, NulError> {
    CString::new(input.into_vec())
}

From &CStr

use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
use std::str::Utf8Error;

pub fn c_str_to_str(input: &CStr) -> Result<&str, Utf8Error> {
    input.to_str()
}

pub fn c_str_to_string(input: &CStr) -> Result<String, Utf8Error> {
    input.to_str().map(|s| s.to_string())
}

pub fn c_str_to_u8_slice(input: &CStr) -> &[u8] {
    input.to_bytes()
}

pub fn c_str_to_u8_vec(input: &CStr) -> Vec<u8> {
    input.to_bytes().to_vec()
}

// This conversion is only allowed on Unix.
pub fn c_str_to_path_unix(input: &CStr) -> &Path {
    Path::new(OsStr::from_bytes(input.to_bytes()))
}

// This conversion is only allowed on Unix.
pub fn c_str_to_path_buf_unix(input: &CStr) -> PathBuf {
    Path::new(OsStr::from_bytes(input.to_bytes())).to_path_buf()
}

// This conversion is only allowed on Unix.
pub fn c_str_to_os_str_unix(input: &CStr) -> &OsStr {
    OsStr::from_bytes(input.to_bytes())
}

// This conversion is only allowed on Unix.
pub fn c_str_to_os_string_unix(input: &CStr) -> OsString {
    OsStr::from_bytes(input.to_bytes()).to_os_string()
}

pub fn c_str_to_c_string(input: &CStr) -> CString {
    CString::from(input)
}

From CString

use std::ffi::IntoStringError;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};
use std::str::Utf8Error;

pub fn c_string_to_str(input: &CString) -> Result<&str, Utf8Error> {
    input.as_c_str().to_str()
}

pub fn c_string_to_string(input: CString) -> Result<String, IntoStringError> {
    input.into_string()
}

pub fn c_string_to_u8_slice(input: &CString) -> &[u8] {
    input.as_bytes()
}

pub fn c_string_to_u8_vec(input: CString) -> Vec<u8> {
    input.into_bytes()
}

// This conversion is only allowed on Unix.
pub fn c_string_to_path_unix(input: &CString) -> &Path {
    Path::new(OsStr::from_bytes(input.as_bytes()))
}

// This conversion is only allowed on Unix.
pub fn c_string_to_path_buf_unix(input: CString) -> PathBuf {
    PathBuf::from(OsString::from_vec(input.into_bytes()))
}

// This conversion is only allowed on Unix.
pub fn c_string_to_os_str_unix(input: &CString) -> &OsStr {
    OsStr::from_bytes(input.as_bytes())
}

// This conversion is only allowed on Unix.
pub fn c_string_to_os_string_unix(input: CString) -> OsString {
    OsString::from_vec(input.into_bytes())
}

pub fn c_string_to_c_str(input: &CString) -> &CStr {
    input.as_c_str()
}