Essential Standard Traits

AsRef and AsMut

The AsRef<T> and AsMut<T> traits in std::convert perform cheap, infallible reference-to-reference conversions (&Self -> &T and &mut Self -> &mut T), enabling functions to accept multiple wrapper or borrowed types without copying or taking ownership.

Trait Definitions

pub trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}

pub trait AsMut<T: ?Sized> {
    fn as_mut(&mut self) -> &mut T;
}

Because T is bound by ?Sized, the target type T is frequently an unsized slice or trait object, such as str, [u8], Path, or OsStr.

Common Standard Library AsRef Implementations

Source Type Implements AsRef<T> For
String and &str str, [u8], OsStr, Path
Vec<T> and &[T] [T]
PathBuf and &Path Path, OsStr
Box<T>, Rc<T>, Arc<T> T

Accepting Flexible Borrowed Inputs with impl AsRef<T>

Standard library filesystem functions (such as std::fs::read_to_string(path: impl AsRef<Path>)) use AsRef<Path> so callers can pass a &str, String, &Path, or PathBuf seamlessly. You can apply the same pattern with AsRef<str> or AsRef<[u8]>:

fn count_non_empty_lines(text: impl AsRef<str>) -> usize {
    text.as_ref()
        .lines()
        .filter(|line| !line.trim().is_empty())
        .count()
}

fn main() {
    let literal: &str = "first\n\nsecond\n";
    let owned: String = String::from("alpha\nbeta\ngamma");

    println!("From &str:   {}", count_non_empty_lines(literal));
    println!("From String: {}", count_non_empty_lines(&owned));
    println!("From owned:  {}", count_non_empty_lines(owned));
}
From &str:   2
From String: 3
From owned:  3

Mutating Inner Buffers with AsMut<[T]>

Implementing or bounding by AsMut<[T]> allows generic in-place algorithms to operate on fixed-size arrays, slices, or Vec<T> alike:

fn zero_out(mut buffer: impl AsMut<[u8]>) {
    for byte in buffer.as_mut() {
        *byte = 0;
    }
}

fn main() {
    let mut arr = [1_u8, 2, 3, 4];
    let mut vec = vec![9_u8, 8, 7];

    zero_out(&mut arr);
    zero_out(&mut vec);

    println!("Array: {arr:?}");
    println!("Vec:   {vec:?}");
}
Array: [0, 0, 0, 0]
Vec:   [0, 0, 0]