faster_path 0.0.2

Alternative to Pathname
Documentation
#![feature(test)]
extern crate libc;
extern crate test;
use std::path::MAIN_SEPARATOR;

static SEP: u8 = MAIN_SEPARATOR as u8;

pub fn extract_last_path_segment_str(path: &str) -> &str {
  path.trim_right_matches(MAIN_SEPARATOR).rsplit(MAIN_SEPARATOR).next().unwrap_or("")
}

pub fn extract_last_path_segment_bytes(mut path: &str) -> &str {
  // Works with bytes directly because MAIN_SEPARATOR is always in the ASCII 7-bit range so we can
  // avoid the overhead of full UTF-8 processing.
  path = match path.bytes().rposition(|b| b != SEP) {
    Some(pos) => &path[..pos + 1],
    _ => &path[..0]
  };
  if let Some(pos) = path.bytes().rposition(|b| b == SEP) {
    path = &path[pos + 1..];
  }
  path
}

pub fn extract_last_path_segment_pointer(path: &str) -> &str {
  // Works with bytes directly because MAIN_SEPARATOR is always in the ASCII 7-bit range so we can
  // avoid the overhead of full UTF-8 processing.
  let ptr = path.as_ptr();
  let mut i = path.len() as isize - 1;
  while i >= 0 {
    let c = unsafe { *ptr.offset(i) };
    if c != SEP { break; };
    i -= 1;
  }
  let end = (i + 1) as usize;
  while i >= 0 {
    let c = unsafe { *ptr.offset(i) };
    if c == SEP {
      return &path[(i + 1) as usize..end];
    };
    i -= 1;
  }
  &path[..end]
}


#[cfg(test)]
mod tests {
  use super::*;
  use test::Bencher;
  use test::black_box;

  static PATH_FOR_BENCH: &'static str = "/hellooooooooo/woλλλλrλd/";

  #[bench]
  fn bench_extract_last_path_segment_bytes(b: &mut Bencher) {
    let path = black_box(PATH_FOR_BENCH);
    b.iter(|| extract_last_path_segment_bytes(path));
  }

  #[bench]
  fn bench_extract_last_path_segment_str(b: &mut Bencher) {
    let path = black_box(PATH_FOR_BENCH);
    b.iter(|| extract_last_path_segment_str(path));
  }

  #[bench]
  fn bench_extract_last_path_segment_pointer(b: &mut Bencher) {
    let path = black_box(PATH_FOR_BENCH);
    b.iter(|| extract_last_path_segment_pointer(path));
  }
}