From 80e7a1be359fc0de4eb17056230ae2fc130b7090 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 23 Mar 2016 22:02:36 +0100 Subject: [PATCH 1/2] Mark str::split_at inline --- src/libcore/str/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f9d1902bea7..4584c26bebc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1965,6 +1965,7 @@ fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { self.find(pat) } + #[inline] fn split_at(&self, mid: usize) -> (&str, &str) { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(mid) { From f621193e5ea7ac54fcd37f0e730e955fd9f61200 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 23 Mar 2016 21:57:44 +0100 Subject: [PATCH 2/2] Accept 0 as a valid str char boundary Index 0 must be a valid char boundary (invariant of str that it contains valid UTF-8 data). If we check explicitly for index == 0, that removes the need to read the byte at index 0, so it avoids a trip to the string's memory, and it optimizes out the slicing index' bounds check whenever it is zero. With this change, the following examples all change from having a read of the byte at 0 and a branch to possibly panicing, to having the bounds checking optimized away. ```rust pub fn split(s: &str) -> (&str, &str) { s.split_at(0) } pub fn both(s: &str) -> &str { &s[0..s.len()] } pub fn first(s: &str) -> &str { &s[..0] } pub fn last(s: &str) -> &str { &s[0..] } ``` --- src/libcore/str/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 4584c26bebc..f033f50e59e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1892,7 +1892,10 @@ fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str #[inline] fn is_char_boundary(&self, index: usize) -> bool { - if index == self.len() { return true; } + // 0 and len are always ok. + // Test for 0 explicitly so that it can optimize out the check + // easily and skip reading string data for that case. + if index == 0 || index == self.len() { return true; } match self.as_bytes().get(index) { None => false, Some(&b) => b < 128 || b >= 192,