src/basename.rs in faster_path-0.2.2 vs src/basename.rs in faster_path-0.2.3
- old
+ new
@@ -1,23 +1,29 @@
-extern crate array_tool;
-use path_parsing::extract_last_path_segment;
-use self::array_tool::string::Squeeze;
+extern crate memchr;
+use self::memchr::memrchr;
+use path_parsing::{SEP, last_non_sep_i};
-pub fn basename(pth: &str, ext: &str) -> String {
- // Known edge case
- match &pth.squeeze("/")[..] {
- "/" => { return "/".to_string() }
- _ => {}
+pub fn basename<'a>(pth: &'a str, ext: &str) -> &'a str {
+ let name_end = (last_non_sep_i(pth) + 1) as usize;
+ // Known edge case, all '/'.
+ if !pth.is_empty() && name_end == 0 {
+ return &pth[..1];
}
-
- let mut name = extract_last_path_segment(pth);
-
+ let name_start = match memrchr(SEP, &pth.as_bytes()[..name_end]) {
+ Some(i) => i + 1,
+ _ => 0
+ };
+ let mut name = &pth[name_start..name_end];
if ext == ".*" {
- if let Some(dot_i) = name.rfind('.') {
- name = &name[0..dot_i];
+ if let Some(dot_i) = memrchr('.' as u8, name.as_bytes()) {
+ name = &name[..dot_i];
}
} else if name.ends_with(ext) {
name = &name[..name.len() - ext.len()];
};
- name.to_string()
+ name
}
+#[test]
+fn edge_case_all_seps() {
+ assert_eq!("/", basename("///", ".*"));
+}