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("")
}