I was looking through Rust\'s source code to better acquaint myself with the language. I came across this snippet.
// Collect program arguments as a Vec
This is just a way to explicitly coerce from String to &str. In this case, the [..] is actually unnecessary as Deref coercions means that parse_name(&args[1]) is valid too: &String will borrow to &str implicitly.
The [ ] indexing operator is calling the std::ops::Index trait, and the .. syntax is creating a std::ops::RangeFull value. cmd is a Vec<String>, since std::env::args() returns an Iterator over Strings.
Hence, the foo[..] syntax is calling the implementation of Index<RangeFull> for String (which you can see in the list of Implementors on the Index page). The implementation looks like:
impl ops::Index<ops::RangeFull> for String {
type Output = str;
#[inline]
fn index(&self, _index: ops::RangeFull) -> &str {
unsafe { mem::transmute(&*self.vec) }
}
}
The &*self.vec is borrowing the String's internal Vec<u8> to &[u8], and then the transmute is explicitly casting that to a &str, which is safe because String's API ensures that the internal Vec<u8> is valid UTF-8, which is what str requires.
Two periods (..) is the range operator. You can find this in the Operators and Symbols Appendix of the Rust book. There are six flavors:
1..101....10..1..=10..=10When no item occupies an end position, the range goes on "forever" in that direction.
This combines with the Index trait (or IndexMut, if mutation is required). In your example, you have a string slice (kind of, see next point) that you are applying indexing to: "foo"[2..].
Specifically, &str implements Index as
Returns a slice of the given string from the byte range
Then there's a third bit of ergonomics happening: Deref (or DerefMut in similar cases). String implements Deref by returning a &str, so any method available to a &str is available to a String.