From 4f18c3b938f051fea0ac93a3ee45b9b62013e834 Mon Sep 17 00:00:00 2001 From: "Daniel P. Clark" <6ftdan@gmail.com> Date: Mon, 11 Sep 2017 21:30:07 -0400 Subject: [PATCH] fin rewriting to ruru & dropped libc --- Cargo.lock | 1 - Cargo.toml | 3 +- Rakefile | 6 ++ benches/path_parsing.rs | 72 --------------------- lib/faster_path.rb | 53 +++++++-------- lib/ffi/basename.rb | 21 ------ lib/ffi/dirname.rb | 21 ------ lib/ffi/extname.rb | 21 ------ src/basename.rs | 50 +++++---------- src/both_are_blank.rs | 22 ------- src/dirname.rs | 61 +++++++----------- src/extname.rs | 15 ++--- src/free.rs | 17 ----- src/has_trailing_separator.rs | 27 -------- src/is_blank.rs | 15 ----- src/is_directory.rs | 18 ------ src/is_relative.rs | 16 ----- src/lib.rs | 117 +++++++++++++++++++++++++--------- src/plus.rs | 4 +- test/basename_test.rb | 8 --- test/extname_test.rb | 4 -- 21 files changed, 162 insertions(+), 410 deletions(-) delete mode 100644 benches/path_parsing.rs delete mode 100644 lib/ffi/basename.rb delete mode 100644 lib/ffi/dirname.rb delete mode 100644 lib/ffi/extname.rb delete mode 100644 src/both_are_blank.rs delete mode 100644 src/free.rs delete mode 100644 src/has_trailing_separator.rs delete mode 100644 src/is_blank.rs delete mode 100644 src/is_directory.rs delete mode 100644 src/is_relative.rs diff --git a/Cargo.lock b/Cargo.lock index 5dc5364..ff1e28a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,6 @@ name = "faster_path" version = "0.0.1" dependencies = [ "array_tool 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "ruru 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 3a93779..9bf8eb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,8 @@ readme = "README.md" [lib] name = "faster_path" -crate-type = ["cdylib"] +crate-type = ["dylib"] [dependencies] -libc = "0.2.30" ruru = "0.9.3" array_tool = "0.4.1" diff --git a/Rakefile b/Rakefile index c095e1d..fca36c4 100644 --- a/Rakefile +++ b/Rakefile @@ -29,11 +29,14 @@ task :libruby_release do filename = RbConfig::CONFIG["LIBRUBY_ALIASES"].split(" ").first libfile = File.join(RbConfig::CONFIG["libdir"], filename) deps = "target/release/deps" + + printf "Copying libruby.so ... " unless File.exist? "#{deps}/#{filename}" FileUtils.mkdir_p deps FileUtils.cp libfile, deps end exit 1 unless File.exist? "#{deps}/#{filename}" + puts "libruby.so copied." end desc "Add libruby to debug deps" @@ -41,11 +44,14 @@ task :libruby_debug do filename = RbConfig::CONFIG["LIBRUBY_ALIASES"].split(" ").first libfile = File.join(RbConfig::CONFIG["libdir"], filename) deps = "target/debug/deps" + + printf "Copying libruby.so ... " unless File.exist? "#{deps}/#{filename}" FileUtils.mkdir_p deps FileUtils.cp libfile, deps end exit 1 unless File.exist? "#{deps}/#{filename}" + puts "libruby.so copied." end desc "Build Rust extension" diff --git a/benches/path_parsing.rs b/benches/path_parsing.rs deleted file mode 100644 index 397a870..0000000 --- a/benches/path_parsing.rs +++ /dev/null @@ -1,72 +0,0 @@ -#![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)); - } -} diff --git a/lib/faster_path.rb b/lib/faster_path.rb index 6c5290a..d34b2a5 100644 --- a/lib/faster_path.rb +++ b/lib/faster_path.rb @@ -16,14 +16,14 @@ module FasterPath FasterPathname.class_eval do private :add_trailing_separator + private :basename private :chop_basename + private :dirname + private :entries + private :extname private :plus end - require_relative 'ffi/basename' - require_relative 'ffi/dirname' - require_relative 'ffi/extname' - def self.rust_arch_bits Rust.rust_arch_bits end @@ -33,19 +33,19 @@ def self.ruby_arch_bits end def self.absolute?(pth) - FasterPathname.allocate.send(:absolute?, pth.to_s) + FasterPathname.allocate.send(:absolute?, pth) end - def self.directory?(pth) - Rust.is_directory(pth) + def self.add_trailing_separator(pth) + FasterPathname.allocate.send(:add_trailing_separator, pth) end - def self.relative?(pth) - Rust.is_relative(pth) + def self.blank?(str) + FasterPathname.allocate.send(:blank?, str) end - def self.dirname(pth) - Dirname::Binding.dirname(pth).to_s + def self.basename(pth, ext="") + FasterPathname.allocate.send(:basename, pth, ext) end def self.chop_basename(pth) @@ -53,32 +53,32 @@ def self.chop_basename(pth) result unless result.empty? end - def self.blank?(str) - Rust.is_blank(str) + def self.directory?(pth) + FasterPathname.allocate.send(:directory?, pth) end - def self.basename(pth, ext="") - Basename::Binding.basename(pth, ext).to_s + def self.dirname(pth) + FasterPathname.allocate.send(:dirname, pth) end - def self.plus(pth, pth2) - FasterPathname.allocate.send(:plus, pth.to_s, pth2.to_s) + def self.entries(pth) + FasterPathname.allocate.send(:entries, pth) end - def self.add_trailing_separator(pth) - FasterPathname.allocate.send(:add_trailing_separator, pth.to_s) + def self.extname(pth) + FasterPathname.allocate.send(:extname, pth) end def self.has_trailing_separator?(pth) - Rust.has_trailing_separator(pth) + FasterPathname.allocate.send(:has_trailing_separator?, pth) end - def self.extname(pth) - Extname::Binding.extname(pth).to_s + def self.plus(pth, pth2) + FasterPathname.allocate.send(:plus, pth.to_s, pth2.to_s) end - def self.entries(pth) - FasterPathname.allocate.send(:entries, pth) + def self.relative?(pth) + FasterPathname.allocate.send(:relative?, pth) end module Rust @@ -86,11 +86,6 @@ module Rust ffi_lib ::FasterPath::FFI_LIBRARY attach_function :rust_arch_bits, [], :int32 - attach_function :is_directory, [ :string ], :bool - attach_function :is_relative, [ :string ], :bool - attach_function :is_blank, [ :string ], :bool - attach_function :both_are_blank, [ :string, :string ], :bool - attach_function :has_trailing_separator, [ :string ], :bool end private_constant :Rust end diff --git a/lib/ffi/basename.rb b/lib/ffi/basename.rb deleted file mode 100644 index af04ccf..0000000 --- a/lib/ffi/basename.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'ffi' - -class FasterPath::Basename < FFI::AutoPointer - def self.release(ptr) - !null? and Binding.free(ptr) - end - - def to_s - @str ||= begin - null? ? nil : read_string.force_encoding('UTF-8') - end - end - - module Binding - extend FFI::Library - ffi_lib ::FasterPath::FFI_LIBRARY - - attach_function :basename, :basename, [ :string, :string ], ::FasterPath::Basename - attach_function :free, :free_string, [ ::FasterPath::Basename ], :void - end -end diff --git a/lib/ffi/dirname.rb b/lib/ffi/dirname.rb deleted file mode 100644 index 207000e..0000000 --- a/lib/ffi/dirname.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'ffi' - -class FasterPath::Dirname < FFI::AutoPointer - def self.release(ptr) - !null? and Binding.free(ptr) - end - - def to_s - @str ||= begin - null? ? nil : read_string.force_encoding('UTF-8') - end - end - - module Binding - extend FFI::Library - ffi_lib ::FasterPath::FFI_LIBRARY - - attach_function :dirname, :dirname, [ :string ], ::FasterPath::Dirname - attach_function :free, :free_string, [ ::FasterPath::Dirname ], :void - end -end diff --git a/lib/ffi/extname.rb b/lib/ffi/extname.rb deleted file mode 100644 index 52fe4c6..0000000 --- a/lib/ffi/extname.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'ffi' - -class FasterPath::Extname < FFI::AutoPointer - def self.release(ptr) - !null? and Binding.free(ptr) - end - - def to_s - @str ||= begin - null? ? nil : read_string.force_encoding('UTF-8') - end - end - - module Binding - extend FFI::Library - ffi_lib ::FasterPath::FFI_LIBRARY - - attach_function :extname, :extname, [ :string ], ::FasterPath::Extname - attach_function :free, :free_string, [ ::FasterPath::Extname ], :void - end -end diff --git a/src/basename.rs b/src/basename.rs index 627b041..959fc25 100644 --- a/src/basename.rs +++ b/src/basename.rs @@ -1,41 +1,23 @@ -use libc::c_char; -use std::ffi::{CStr, CString}; +extern crate array_tool; +use path_parsing::extract_last_path_segment; +use self::array_tool::string::Squeeze; -#[no_mangle] -pub extern "C" fn basename(c_pth: *const c_char, c_ext: *const c_char) -> *const c_char { - if c_pth.is_null() || c_ext.is_null() { - return c_pth; +pub fn basename(pth: &str, ext: &str) -> String { + // Known edge case + match &pth.squeeze("/")[..] { + "/" => { return "/".to_string() } + _ => {} } - let pth = unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap(); - let ext = unsafe { CStr::from_ptr(c_ext) }.to_str().unwrap(); - let name = rust::basename(pth, ext); - - CString::new(name).unwrap().into_raw() -} - -pub mod rust { - extern crate array_tool; - use path_parsing::extract_last_path_segment; - use self::array_tool::string::Squeeze; + let mut name = extract_last_path_segment(pth); - pub fn basename(pth: &str, ext: &str) -> String { - // Known edge case - match &pth.squeeze("/")[..] { - "/" => { return "/".to_string() } - _ => {} + if ext == ".*" { + if let Some(dot_i) = name.rfind('.') { + name = &name[0..dot_i]; } - - let mut name = extract_last_path_segment(pth); - - if ext == ".*" { - if let Some(dot_i) = name.rfind('.') { - name = &name[0..dot_i]; - } - } else if name.ends_with(ext) { - name = &name[..name.len() - ext.len()]; - }; - name.to_string() - } + } else if name.ends_with(ext) { + name = &name[..name.len() - ext.len()]; + }; + name.to_string() } diff --git a/src/both_are_blank.rs b/src/both_are_blank.rs deleted file mode 100644 index 13a6458..0000000 --- a/src/both_are_blank.rs +++ /dev/null @@ -1,22 +0,0 @@ -use libc::c_char; -use std::ffi::{CStr}; -use std::str; - -#[no_mangle] -pub extern "C" fn both_are_blank(s1: *const c_char, s2: *const c_char) -> bool { - let c_str1 = unsafe { - if s1.is_null() { - return true; - } - CStr::from_ptr(s1) - }; - let c_str2 = unsafe { - if s2.is_null() { - return true; - } - CStr::from_ptr(s2) - }; - - str::from_utf8(c_str1.to_bytes()).unwrap().trim().is_empty() && - str::from_utf8(c_str2.to_bytes()).unwrap().trim().is_empty() -} diff --git a/src/dirname.rs b/src/dirname.rs index a12b581..9d10af7 100644 --- a/src/dirname.rs +++ b/src/dirname.rs @@ -1,46 +1,31 @@ -use libc::c_char; -use std::ffi::{CStr, CString}; +use std::path::MAIN_SEPARATOR; +use path_parsing::{last_sep_i, last_non_sep_i, last_non_sep_i_before}; -#[no_mangle] -pub extern "C" fn dirname(path: *const c_char) -> *const c_char { - if path.is_null() { - return path +pub fn dirname(path: &str) -> String { + let r_str = path; + if r_str.is_empty() { + return ".".to_string(); } - let r_str = unsafe { CStr::from_ptr(path) }.to_str().unwrap(); - - CString::new(rust::dirname(r_str)).unwrap().into_raw() -} - -pub mod rust { - use std::path::MAIN_SEPARATOR; - use path_parsing::{last_sep_i, last_non_sep_i, last_non_sep_i_before}; - - pub fn dirname(path: &str) -> String { - let r_str = path; - if r_str.is_empty() { - return ".".to_string(); - } - let non_sep_i = last_non_sep_i(r_str); - if non_sep_i == -1 { - return MAIN_SEPARATOR.to_string(); - } - let sep_i = last_sep_i(r_str, non_sep_i); - if sep_i == -1 { - return ".".to_string(); - } - if sep_i == 0 { - return MAIN_SEPARATOR.to_string(); - } - let non_sep_i2 = last_non_sep_i_before(r_str, sep_i); - if non_sep_i2 != -1 { - return r_str[..(non_sep_i2 + 1) as usize].to_string(); - } else { - return MAIN_SEPARATOR.to_string(); - } + let non_sep_i = last_non_sep_i(r_str); + if non_sep_i == -1 { + return MAIN_SEPARATOR.to_string(); + } + let sep_i = last_sep_i(r_str, non_sep_i); + if sep_i == -1 { + return ".".to_string(); + } + if sep_i == 0 { + return MAIN_SEPARATOR.to_string(); + } + let non_sep_i2 = last_non_sep_i_before(r_str, sep_i); + if non_sep_i2 != -1 { + return r_str[..(non_sep_i2 + 1) as usize].to_string(); + } else { + return MAIN_SEPARATOR.to_string(); } } #[test] fn returns_dot_for_empty_string(){ - assert_eq!(rust::dirname(""), ".".to_string()); + assert_eq!(dirname(""), ".".to_string()); } diff --git a/src/extname.rs b/src/extname.rs index a5c04d7..4df8cfc 100644 --- a/src/extname.rs +++ b/src/extname.rs @@ -1,20 +1,13 @@ -use libc::c_char; -use std::ffi::{CStr, CString}; use path_parsing::extract_last_path_segment; -#[no_mangle] -pub extern "C" fn extname(c_pth: *const c_char) -> *const c_char { - if c_pth.is_null() { - return c_pth - } - - let name = extract_last_path_segment(unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap()); +pub fn extname(pth: &str) -> String { + let name = extract_last_path_segment(pth); if let Some(dot_i) = name.rfind('.') { if dot_i > 0 && dot_i < name.len() - 1 && name[..dot_i].chars().rev().next().unwrap() != '.' { - return CString::new(&name[dot_i..]).unwrap().into_raw() + return String::from(&name[dot_i..]) } } - CString::new("").unwrap().into_raw() + String::from("") } diff --git a/src/free.rs b/src/free.rs deleted file mode 100644 index a4683b6..0000000 --- a/src/free.rs +++ /dev/null @@ -1,17 +0,0 @@ -use libc::c_char; -use std::ffi::CString; -// use ruby_array::RubyArray; - -#[no_mangle] -pub extern "C" fn free_string(s: *mut c_char) { - unsafe { - if s.is_null() { return } - CString::from_raw(s) - }; -} - -// #[no_mangle] -// pub extern "C" fn free_array(ra: *mut RubyArray) { -// if ra.is_null() { return } -// unsafe { Box::from_raw(ra); } -// } diff --git a/src/has_trailing_separator.rs b/src/has_trailing_separator.rs deleted file mode 100644 index 4f076ea..0000000 --- a/src/has_trailing_separator.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::path::{Path, MAIN_SEPARATOR}; -use libc::c_char; -use std::ffi::CStr; -use std::str; - -#[no_mangle] -pub extern "C" fn has_trailing_separator(string: *const c_char) -> bool { - let c_str = unsafe { - if string.is_null() { - return false - } - CStr::from_ptr(string) - }; - - let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or(""); - let path = Path::new(r_str); - let last_component = path.iter().last(); - if last_component.is_none() { - false - } else { - let mut parts: Vec<&str> = r_str.rsplit_terminator(MAIN_SEPARATOR).collect(); - parts.retain(|x| !x.is_empty()); - let last_part = parts.first().unwrap_or(&"").chars().last().unwrap_or(MAIN_SEPARATOR); - let last_char = r_str.chars().last().unwrap(); - (last_part != last_char) && (last_char == MAIN_SEPARATOR) - } -} diff --git a/src/is_blank.rs b/src/is_blank.rs deleted file mode 100644 index 09ca454..0000000 --- a/src/is_blank.rs +++ /dev/null @@ -1,15 +0,0 @@ -use libc::c_char; -use std::ffi::{CStr}; -use std::str; - -#[no_mangle] -pub extern "C" fn is_blank(string: *const c_char) -> bool { - let c_str = unsafe { - if string.is_null() { - return true; - } - CStr::from_ptr(string) - }; - - str::from_utf8(c_str.to_bytes()).unwrap().trim().is_empty() -} diff --git a/src/is_directory.rs b/src/is_directory.rs deleted file mode 100644 index 8c64e95..0000000 --- a/src/is_directory.rs +++ /dev/null @@ -1,18 +0,0 @@ -use libc::c_char; -use std::ffi::{CStr}; -use std::str; -use std::path::Path; - -#[no_mangle] -pub extern "C" fn is_directory(string: *const c_char) -> bool { - let c_str = unsafe { - if string.is_null() { - return false; - } - CStr::from_ptr(string) - }; - - let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or(""); - - Path::new(r_str).is_dir() -} diff --git a/src/is_relative.rs b/src/is_relative.rs deleted file mode 100644 index a32da75..0000000 --- a/src/is_relative.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::path::MAIN_SEPARATOR; -use libc::c_char; -use std::ffi::{CStr}; - -#[no_mangle] -pub extern "C" fn is_relative(path: *const c_char) -> bool { - if path.is_null() { - return false; - } - let r_str = unsafe { CStr::from_ptr(path) }.to_str().unwrap(); - - match r_str.chars().next() { - Some(c) => c != MAIN_SEPARATOR, - None => true - } -} diff --git a/src/lib.rs b/src/lib.rs index 90cbb18..33ec13d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,54 +4,61 @@ // http://apache.org/licenses/LICENSE-2.0> or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. -extern crate libc; - #[macro_use] extern crate ruru; class!(FasterPathname); -pub mod free; -pub mod is_directory; -pub mod is_relative; -pub mod is_blank; -pub mod both_are_blank; -pub mod basename; -pub mod plus; -pub mod dirname; -pub mod chop_basename; -pub mod has_trailing_separator; -pub mod extname; +mod basename; +mod chop_basename; +mod dirname; +mod extname; +mod plus; pub mod rust_arch_bits; mod path_parsing; use ruru::{Class, Object, RString, Boolean, Array}; -use std::path::MAIN_SEPARATOR; +use std::path::{MAIN_SEPARATOR,Path}; use std::fs; methods!( FasterPathname, _itself, - fn add_trailing_separator(path: RString) -> RString { - let pth = path.ok().unwrap(); - let x = format!("{}{}", pth.to_str(), "a"); + fn r_add_trailing_separator(pth: RString) -> RString { + let p = pth.ok().unwrap(); + let x = format!("{}{}", p.to_str(), "a"); match x.rsplit_terminator(MAIN_SEPARATOR).next() { - Some("a") => pth, - _ => RString::new(format!("{}{}", pth.to_str(), MAIN_SEPARATOR).as_str()) + Some("a") => p, + _ => RString::new(format!("{}{}", p.to_str(), MAIN_SEPARATOR).as_str()) } } - fn is_absolute(path: RString) -> Boolean { - Boolean::new(match path.ok().unwrap().to_str().chars().next() { + fn r_is_absolute(pth: RString) -> Boolean { + Boolean::new(match pth.ok().unwrap_or(RString::new("")).to_str().chars().next() { Some(c) => c == MAIN_SEPARATOR, None => false }) } - fn chop_basename(path: RString) -> Array { + fn r_basename(pth: RString, ext: RString) -> RString { + RString::new( + &basename::basename( + pth.ok().unwrap_or(RString::new("")).to_str(), + ext.ok().unwrap_or(RString::new("")).to_str() + )[..] + ) + } + + fn r_is_blank(string: RString) -> Boolean { + Boolean::new( + string.ok().unwrap_or(RString::new("")).to_str().trim().is_empty() + ) + } + + fn r_chop_basename(pth: RString) -> Array { let mut arr = Array::with_capacity(2); - let results = chop_basename::chop_basename(path.ok().unwrap_or(RString::new("")).to_str()); + let results = chop_basename::chop_basename(pth.ok().unwrap_or(RString::new("")).to_str()); match results { Some((dirname, basename)) => { arr.push(RString::new(&dirname[..])); @@ -62,8 +69,24 @@ methods!( } } - fn entries(string: RString) -> Array { - let files = fs::read_dir(string.ok().unwrap_or(RString::new("")).to_str()).unwrap(); + fn r_is_directory(pth: RString) -> Boolean { + Boolean::new( + Path::new( + pth.ok().unwrap_or(RString::new("")).to_str() + ).is_dir() + ) + } + + fn r_dirname(pth: RString) -> RString { + RString::new( + &dirname::dirname( + pth.ok().unwrap_or(RString::new("")).to_str() + )[..] + ) + } + + fn r_entries(pth: RString) -> Array { + let files = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()).unwrap(); let mut arr = Array::new(); arr.push(RString::new(".")); @@ -77,19 +100,51 @@ methods!( arr } - fn plus(pth1: RString, pth2: RString) -> RString { + fn r_extname(pth: RString) -> RString { + RString::new( + &extname::extname(pth.ok().unwrap_or(RString::new("")).to_str())[..] + ) + } + + fn r_has_trailing_separator(pth: RString) -> Boolean { + let v = pth.ok().unwrap_or(RString::new("")); + match chop_basename::chop_basename(v.to_str()) { + Some((a,b)) => { + Boolean::new(a.len() + b.len() < v.to_str().len()) + }, + _ => Boolean::new(false) + } + } + + fn r_plus(pth1: RString, pth2: RString) -> RString { RString::new(&plus::plus_paths(pth1.ok().unwrap().to_str(), pth2.ok().unwrap().to_str())[..]) } + + fn r_is_relative(pth: RString) -> Boolean { + Boolean::new( + match pth.ok().unwrap_or(RString::new(&MAIN_SEPARATOR.to_string()[..])).to_str().chars().next() { + Some(c) => c != MAIN_SEPARATOR, + None => true + } + ) + } ); #[allow(non_snake_case)] #[no_mangle] pub extern "C" fn Init_faster_pathname(){ Class::new("FasterPathname", None).define(|itself| { - itself.def("absolute?", is_absolute); - itself.def("add_trailing_separator", add_trailing_separator); - itself.def("chop_basename", chop_basename); - itself.def("entries", entries); - itself.def("plus", plus); + itself.def("absolute?", r_is_absolute); + itself.def("add_trailing_separator", r_add_trailing_separator); + itself.def("basename", r_basename); + itself.def("blank?", r_is_blank); + itself.def("chop_basename", r_chop_basename); + itself.def("directory?", r_is_directory); + itself.def("dirname", r_dirname); + itself.def("entries", r_entries); + itself.def("extname", r_extname); + itself.def("has_trailing_separator?", r_has_trailing_separator); + itself.def("plus", r_plus); + itself.def("relative?", r_is_relative); }); } diff --git a/src/plus.rs b/src/plus.rs index 407e8c9..266444b 100644 --- a/src/plus.rs +++ b/src/plus.rs @@ -2,8 +2,8 @@ extern crate array_tool; use std::path::Path; use std::str; use chop_basename::chop_basename; -use basename::rust::basename; -use dirname::rust::dirname; +use basename::basename; +use dirname::dirname; use self::array_tool::vec::Shift; use std::ops::Index; diff --git a/test/basename_test.rb b/test/basename_test.rb index 11f9f82..ab1b6ca 100644 --- a/test/basename_test.rb +++ b/test/basename_test.rb @@ -1,14 +1,6 @@ require 'test_helper' class BasenameTest < Minitest::Test - def test_nil_inputs - assert_nil FasterPath.basename(nil, nil) - assert_equal FasterPath.basename('', nil), "" - assert_nil FasterPath.basename(nil, '') - assert_equal FasterPath.basename('asdf', nil), "asdf" - assert_nil FasterPath.basename(nil, 'asdf') - end - # Tests copied from https://searchcode.com/codesearch/view/12785140/ def test_it_creates_basename_correctly assert_equal FasterPath.basename('/home/gumby/work/ruby.rb'), 'ruby.rb' diff --git a/test/extname_test.rb b/test/extname_test.rb index 38b4e93..e485b17 100644 --- a/test/extname_test.rb +++ b/test/extname_test.rb @@ -1,10 +1,6 @@ require 'test_helper' class ExtnameTest < Minitest::Test - def test_nil_inputs - assert_nil FasterPath.extname(nil) - end - def test_extname assert_equal ".rb", FasterPath.extname("foo.rb") assert_equal ".rb", FasterPath.extname("/foo/bar.rb")