Both Into<String>
and AsRef<str>
(as described in the other answers) will accept String
, &str
, and &String
. They are different and which one to use will depend on your situation.
If you need an owned string then use Into<String>
Using AsRef<str>
here will rob your caller of the opportunity to avoid a string copy
struct Favorites {
things: Vec<String>
}
impl Favorites {
pub fn add_thing(&mut self, thing: impl Into<String>) {
self.things.push(thing.into())
}
}
fn main() {
let mut favs = Favorites { things: Vec::new() };
// String literals are static references and we can't ever get
// the owned value so a clone of the bytes is necessary
favs.add_thing("hi"); // Contents cloned implicitly
// std::env::var already makes a new string. We avoid
// cloning this value needlessly because we used Into<String>
let my_fav = std::env::var("USER_FAVORITE");
if let Ok(my_fav) = my_fav {
favs.add_thing(my_fav); // No clone
}
// Note, there is a `impl From<&String> for String` which
// makes a sneaky clone. Watch out for this
let my_fav = std::env::var("USER_FAVORITE");
if let Ok(my_fav) = my_fav {
favs.add_thing(&my_fav); // Contents cloned implicitly
}
}
If you just need a string reference then use AsRef<str>
Using Into<String>
here will force a string copy where none is needed
fn count_whitespace(value: impl AsRef<str>) -> usize {
value.as_ref().chars().filter(|c| c.is_whitespace()).count()
}
fn main() {
let my_str = "he llo ";
// Once clone of my_str is made here
let my_string = my_str.to_string();
// No clone of string data is made beyond this point
let num_ws_2 = count_whitespace(&my_string);
let num_ws = count_whitespace(my_string);
let num_ws_3 = count_whitespace(my_str);
dbg!(num_ws, num_ws_2, num_ws_3);
}
Into<String>
variant also works for&String
. – Larondalarosa