stringrustborrowing

How to accept &str, String and &String in a single function?


I want to write a single function, that accepts a &str, a String and a borrowed &String. I've written the following 2 functions:

fn accept_str_and_ref_string(value: &str) {
    println!("value: {}", value);
}

fn accept_str_and_string<S: Into<String>>(value: S) {
    let string_value: String = value.into();
    println!("string_value: {}", string_value);
}

fn main() {
    let str_foo = "foo";
    let string_foo = String::from("foo");

    accept_str_and_ref_string(str_foo);
    accept_str_and_ref_string(&string_foo);

    accept_str_and_string(str_foo);
    accept_str_and_string(string_foo);
}

Is it possible to implement one function so that I can do this:

accept_all_strings(str_foo);
accept_all_strings(&string_foo);
accept_all_strings(string_foo);

Solution

  • You can use the AsRef<str> trait:

    // will accept any object that implements AsRef<str>
    fn print<S: AsRef<str>>(stringlike: S) {
        // call as_ref() to get a &str
        let str_ref = stringlike.as_ref();
    
        println!("got: {:?}", str_ref)
    }
    
    fn main() {
        let a: &str = "str";
        let b: String = String::from("String");
        let c: &String = &b;
    
        print(a);
        print(c);
        print(b);
    }
    

    The print function will support any type that implements AsRef<str>, which includes &str, String and &String.