diff --git a/Rakefile b/Rakefile index b25c822..2542d9d 100644 --- a/Rakefile +++ b/Rakefile @@ -69,17 +69,17 @@ task :init_mspec do |_t| end task test: [:cargo, :minitest, :lint, :pbench, :init_mspec] do |_t| - exec 'spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname' + exec 'bundle exec spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname' end desc "Full mspec results w/o encoding" task mspec_full: :init_mspec do - exec %(bash -c "TEST_MONKEYPATCHES=true WITH_REGRESSION=true spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname") + exec %(bash -c "TEST_MONKEYPATCHES=true WITH_REGRESSION=true bundle exec spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname") end desc "Full mspec results w/ encoding" task mspec_encoding_full: :init_mspec do - exec %(bash -c "ENCODING=1 TEST_MONKEYPATCHES=true WITH_REGRESSION=true mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname") + exec %(bash -c "ENCODING=1 TEST_MONKEYPATCHES=true WITH_REGRESSION=true bundle exec spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname") end Rake::TestTask.new(bench: :build_lib) do |t| diff --git a/src/basename.rs b/src/basename.rs index a663e52..6c03b0e 100644 --- a/src/basename.rs +++ b/src/basename.rs @@ -4,25 +4,24 @@ use self::memchr::memrchr; use path_parsing::{find_last_sep_pos, find_last_non_sep_pos}; -pub fn basename<'a>(path: &'a str, ext: &str) -> &'a str { - let bytes: &[u8] = path.as_bytes(); +pub fn basename<'a>(path: &'a [u8], ext: &str) -> &'a [u8] { let mut left: usize = 0; - let mut right: usize = bytes.len(); - if let Some(last_slash_pos) = find_last_sep_pos(bytes) { + let mut right: usize = path.len(); + if let Some(last_slash_pos) = find_last_sep_pos(path) { if last_slash_pos == right - 1 { - if let Some(pos) = find_last_non_sep_pos(&bytes[..last_slash_pos]) { + if let Some(pos) = find_last_non_sep_pos(&path[..last_slash_pos]) { right = pos + 1; } else { - return "/"; + return "/".as_bytes(); } - if let Some(pos) = find_last_sep_pos(&bytes[..right]) { + if let Some(pos) = find_last_sep_pos(&path[..right]) { left = pos + 1; } } else { left = last_slash_pos + 1; } } - &path[left..left + ext_end(&bytes[left..right], ext)] + &path[left..left + ext_end(&path[left..right], ext)] } fn ext_end(slice: &[u8], ext: &str) -> usize { @@ -44,103 +43,103 @@ fn ext_end(slice: &[u8], ext: &str) -> usize { #[test] fn non_dot_asterisk_ext() { // This is undocumented Ruby functionality. We match it in case some code out there relies on it. - assert_eq!(basename("abc", "b*"), "a"); - assert_eq!(basename("abc", "abc"), "abc"); - assert_eq!(basename("abc", "a*"), "abc"); - assert_eq!(basename("playlist", "l*"), "play"); + assert_eq!(basename("abc".as_bytes(), "b*"), b"a"); + assert_eq!(basename("abc".as_bytes(), "abc"), b"abc"); + assert_eq!(basename("abc".as_bytes(), "a*"), b"abc"); + assert_eq!(basename("playlist".as_bytes(), "l*"), b"play"); // Treated as literal "*": - assert_eq!(basename("playlist", "yl*"), "playlist"); - assert_eq!(basename("playl*", "yl*"), "pla"); + assert_eq!(basename("playlist".as_bytes(), "yl*"), b"playlist"); + assert_eq!(basename("playl*".as_bytes(), "yl*"), b"pla"); } #[test] fn empty() { - assert_eq!(basename("", ""), ""); - assert_eq!(basename("", ".*"), ""); - assert_eq!(basename("", ".a"), ""); + assert_eq!(basename("".as_bytes(), ""), b""); + assert_eq!(basename("".as_bytes(), ".*"), b""); + assert_eq!(basename("".as_bytes(), ".a"), b""); } #[test] fn sep() { - assert_eq!(basename("/", ""), "/"); - assert_eq!(basename("//", ""), "/"); + assert_eq!(basename("/".as_bytes(), ""), b"/"); + assert_eq!(basename("//".as_bytes(), ""), b"/"); } #[test] fn trailing_dot() { - assert_eq!(basename("file.test.", ""), "file.test."); - assert_eq!(basename("file.test.", "."), "file.test"); - assert_eq!(basename("file.test.", ".*"), "file.test"); + assert_eq!(basename("file.test.".as_bytes(), ""), b"file.test."); + assert_eq!(basename("file.test.".as_bytes(), "."), b"file.test"); + assert_eq!(basename("file.test.".as_bytes(), ".*"), b"file.test"); } #[test] fn trailing_dot_dot() { - assert_eq!(basename("a..", ".."), "a"); - assert_eq!(basename("a..", ".*"), "a."); + assert_eq!(basename("a..".as_bytes(), ".."), b"a"); + assert_eq!(basename("a..".as_bytes(), ".*"), b"a."); } #[test] fn dot() { - assert_eq!(basename(".", ""), "."); - assert_eq!(basename(".", "."), "."); - assert_eq!(basename(".", ".*"), "."); + assert_eq!(basename(".".as_bytes(), ""), b"."); + assert_eq!(basename(".".as_bytes(), "."), b"."); + assert_eq!(basename(".".as_bytes(), ".*"), b"."); } #[test] fn dot_dot() { - assert_eq!(basename("..", ""), ".."); - assert_eq!(basename("..", ".*"), ".."); - assert_eq!(basename("..", ".."), ".."); - assert_eq!(basename("..", "..."), ".."); + assert_eq!(basename("..".as_bytes(), ""), b".."); + assert_eq!(basename("..".as_bytes(), ".*"), b".."); + assert_eq!(basename("..".as_bytes(), ".."), b".."); + assert_eq!(basename("..".as_bytes(), "..."), b".."); } #[test] fn non_dot_ext() { - assert_eq!(basename("abc", "bc"), "a"); + assert_eq!(basename("abc".as_bytes(), "bc"), b"a"); } #[test] fn basename_eq_ext() { - assert_eq!(basename(".x", ".x"), ".x"); - assert_eq!(basename(".x", ".*"), ".x"); + assert_eq!(basename(".x".as_bytes(), ".x"), b".x"); + assert_eq!(basename(".x".as_bytes(), ".*"), b".x"); } #[test] fn absolute() { - assert_eq!(basename("/a/b///c", ""), "c"); + assert_eq!(basename("/a/b///c".as_bytes(), ""), b"c"); } #[test] fn trailing_slashes_absolute() { - assert_eq!(basename("/a/b///c//////", ""), "c"); + assert_eq!(basename("/a/b///c//////".as_bytes(), ""), b"c"); } #[test] fn relative() { - assert_eq!(basename("b///c", ""), "c"); + assert_eq!(basename("b///c".as_bytes(), ""), b"c"); } #[test] fn trailing_slashes_relative() { - assert_eq!(basename("b/c//", ""), "c"); + assert_eq!(basename("b/c//".as_bytes(), ""), b"c"); } #[test] fn root() { - assert_eq!(basename("//c", ""), "c"); + assert_eq!(basename("//c".as_bytes(), ""), b"c"); } #[test] fn trailing_slashes_root() { - assert_eq!(basename("//c//", ""), "c"); + assert_eq!(basename("//c//".as_bytes(), ""), b"c"); } #[test] fn trailing_slashes_relative_root() { - assert_eq!(basename("c//", ""), "c"); + assert_eq!(basename("c//".as_bytes(), ""), b"c"); } #[test] fn edge_case_all_seps() { - assert_eq!("/", basename("///", ".*")); + assert_eq!(b"/", basename("///".as_bytes(), ".*")); } diff --git a/src/cleanpath_aggressive.rs b/src/cleanpath_aggressive.rs index d976301..7628883 100644 --- a/src/cleanpath_aggressive.rs +++ b/src/cleanpath_aggressive.rs @@ -27,7 +27,7 @@ pub fn cleanpath_aggressive(path: &str) -> Cow { // pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR // ``` // - if contains_sep(basename(&prefix, "").as_bytes()) { + if contains_sep(basename(&prefix.as_bytes(), "")) { let len = names.iter().rposition(|&c| c != "..").map_or(0, |pos| pos + 1); names.truncate(len); } diff --git a/src/cleanpath_conservative.rs b/src/cleanpath_conservative.rs index f4c7b87..9e48e6c 100644 --- a/src/cleanpath_conservative.rs +++ b/src/cleanpath_conservative.rs @@ -21,7 +21,7 @@ pub fn cleanpath_conservative(path: &str) -> Cow { // pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR // ``` // - if contains_sep(basename(&prefix, "").as_bytes()) { + if contains_sep(basename(&prefix.as_bytes(), "")) { let len = names.iter().rposition(|&c| c != "..").map_or(0, |pos| pos + 1); names.truncate(len); } @@ -31,7 +31,7 @@ pub fn cleanpath_conservative(path: &str) -> Cow { None => return dirname(&prefix).into(), }; - if last_name != ".." && basename(&path, "") == "." { + if last_name != ".." && basename(&path.as_bytes(), "") == ".".as_bytes() { names.reverse(); names.push("."); } else if last_name != "." && last_name != ".." && diff --git a/src/helpers.rs b/src/helpers.rs index e360eb3..115c9e8 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -44,7 +44,14 @@ pub fn anyobject_to_string(item: AnyObject) -> Result { pub fn to_str(maybe_string: &MaybeString) -> &str { match maybe_string { - &Ok(ref rutie_string) => rutie_string.to_str(), + &Ok(ref rutie_string) => rutie_string.to_str_unchecked(), &Err(_) => "", } } + +pub fn to_bytes(maybe_string: &MaybeString) -> &[u8] { + match maybe_string { + &Ok(ref rutie_string) => rutie_string.to_bytes_unchecked(), + &Err(_) => &[], + } +} diff --git a/src/pathname.rs b/src/pathname.rs index b419500..bc29a96 100644 --- a/src/pathname.rs +++ b/src/pathname.rs @@ -8,7 +8,7 @@ use extname; use plus; use relative_path_from; use debug; -use helpers::{TryFrom, to_str}; +use helpers::{TryFrom, to_str, to_bytes}; use path_parsing::{SEP, find_last_non_sep_pos}; use rutie; @@ -23,6 +23,7 @@ use rutie::{ VerifiedObject, Exception as Exc, AnyException as Exception, + Encoding, }; use rutie::types::{Value, ValueType}; use std::borrow::Cow; @@ -105,7 +106,7 @@ pub fn pn_is_absolute(pth: MaybeString) -> Boolean { // pub fn pn_ascend(){} pub fn pn_basename(pth: MaybeString, ext: MaybeString) -> RString { - RString::new_utf8(basename::basename(to_str(&pth), to_str(&ext))) + RString::from_bytes(basename::basename(to_bytes(&pth), to_str(&ext)), &Encoding::utf8()) } pub fn pn_children(pth: MaybeString, with_dir: MaybeBoolean) -> Result {