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("///", ".*")); +}