I've recently been working with some rather String
heavy APIs and have been starting to question the ergonomics and performance of the current conventions.
Let's start with the ergonomics. Trying to write idiomatic Rust I currently have function calls like this:
xml::Element::new("iq".to_string(), Some("jabber:client".to_string()),
vec![("id".to_string(), None, "bind".to_string()),
("type".to_string(), None, "set".to_string())])
The to_string
calls create a lot of noise. With more elements in the Vec
it would be tempting to write this with slices, and then map().collect()
over it.
The second aspect I'm a bit concerned about is performance. It might not be obvious, but calling to_string()
on a &str
currently invokes the whole formatting machinery, generating a lot of code. In the current state of the language this can't really change, since ToString
is implemented for any type implementing fmt::Display
, which makes impl<'a> ToString for &'a str
a conflicting impl
.
There are multiple alternative ways to create String
s from string slices, among them From::from()
, String::from_str()
, and ToOwned::to_owned()
. The later two solve the performance Issue, none of them improve the ergonomics.
In theory I could make the xml::Element::new()
method generic over ToString
. However, that still wouldn't enable passing a mixture of string slices and String
s as part of the Vec
, and it would require invoking the formatting machinery even for String
.
I was wondering how other people are dealing with this. Are there possibly plans to improve this situation in the future, that I'm not aware of? A str!()
macro has occasionally been suggested (also for "consistency" with vec![]
), but was usually dismissed.