src/extname.rs in faster_path-0.2.6 vs src/extname.rs in faster_path-0.3.1

- old
+ new

@@ -1,13 +1,63 @@ -use path_parsing::extract_last_path_segment; +use path_parsing::SEP; +use std::str; +struct ExtnameCoords { + word: bool, + pred: bool, + dot: bool, + start: usize, + end: usize, +} + +impl ExtnameCoords { + pub fn dec(&mut self) { + self.start -= 1; + if !self.word { + self.end -= 1; + } + } +} + pub fn extname(pth: &str) -> &str { - let name = extract_last_path_segment(pth); + let path = pth.as_bytes(); + let mut extname = ExtnameCoords { + word: false, + pred: false, + dot: false, + start: path.len(), + end: path.len(), + }; - if let Some(dot_i) = name.rfind('.') { - if dot_i > 0 && dot_i < name.len() - 1 && name[..dot_i].chars().rev().next().unwrap() != '.' { - return &name[dot_i..] + for &item in path.iter().rev() { + if (item == b'.' && !extname.dot) || item == SEP { + if item == SEP && extname.word { + return "" + } + + if !extname.pred { + extname.dec(); + } + + if extname.word { + extname.dot = true; + } + } else { + if extname.dot { + extname.pred = true; + break; + } else { + extname.word = true; + } + + if !extname.pred { + extname.dec() + } } } - "" + if !extname.pred { + return ""; + } + + str::from_utf8(&path[extname.start..extname.end]).unwrap_or("") }