src/pathname.rs in faster_path-0.3.7 vs src/pathname.rs in faster_path-0.3.8

- old
+ new

@@ -6,12 +6,13 @@ use dirname; use extname; use plus; use relative_path_from; use debug; -use helpers::TryFrom; +use helpers::{TryFrom, to_str}; use pathname_sys::null_byte_check; +use path_parsing::{SEP, find_last_non_sep_pos}; use ruru; use ruru::{ RString, Boolean, @@ -38,11 +39,11 @@ impl Pathname { pub fn new(path: &str) -> Pathname { let mut instance = Class::from_existing("Pathname").allocate(); instance.instance_variable_set("@path", RString::new(path).to_any_object()); - + Pathname { value: instance.value() } } pub fn new_checked(path: AnyObject) -> Result<Pathname, Exception> { let pth: Value = if Class::from_existing("String").case_equals(&path) { @@ -56,18 +57,18 @@ Some("The type for the argument provided to Pathname.new was invalid.") ) ) }; - if null_byte_check(path.value()) { + if null_byte_check(path.value()) { return Err( Exception::new("ArgumentError", Some("pathname contains null byte")) ) } // if it crashes then dup the path string here before assigning to @path let mut instance = Class::from_existing("Pathname").allocate(); instance.instance_variable_set("@path", RString::from(pth).to_any_object()); - + Ok(Pathname { value: instance.value() }) } pub fn to_any_object(&self) -> AnyObject { AnyObject::from(self.value()) @@ -82,15 +83,15 @@ impl TryFrom<AnyObject> for Pathname { type Error = debug::RubyDebugInfo; fn try_from(obj: AnyObject) -> Result<Pathname, Self::Error> { if Class::from_existing("String").case_equals(&obj) { - Ok(Pathname::new(&RString::from(obj.value()).to_string())) + Ok(Pathname::new(&RString::from(obj.value()).to_str())) } else if Class::from_existing("Pathname").case_equals(&obj) { Ok(Pathname::from(obj.value())) } else if obj.respond_to("to_path") { - Ok(Pathname::from(obj.send("to_path", None).value())) + Ok(Pathname::new(&RString::from(obj.send("to_path", None).value()).to_str())) } else { Err(Self::Error::from(obj)) } } } @@ -112,47 +113,39 @@ "Error converting to Pathname" } } pub fn pn_add_trailing_separator(pth: MaybeString) -> RString { - let p = pth.ok().unwrap(); + let p = pth.unwrap(); let x = format!("{}{}", p.to_str(), "a"); match x.rsplit_terminator(MAIN_SEPARATOR).next() { Some("a") => p, _ => RString::new(format!("{}{}", p.to_str(), MAIN_SEPARATOR).as_str()) } } pub fn pn_is_absolute(pth: MaybeString) -> Boolean { - Boolean::new(match pth.ok().unwrap_or(RString::new("")).to_str().chars().next() { - Some(c) => c == MAIN_SEPARATOR, - None => false - }) + Boolean::new(to_str(&pth).as_bytes().get(0) == Some(&SEP)) } // pub fn pn_ascend(){} pub fn pn_basename(pth: MaybeString, ext: MaybeString) -> RString { - RString::new( - basename::basename( - pth.ok().unwrap_or(RString::new("")).to_str(), - ext.ok().unwrap_or(RString::new("")).to_str() - ) - ) + RString::new(basename::basename(to_str(&pth), to_str(&ext))) } -pub fn pn_children(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject { - let val = pth.ok().unwrap_or(RString::new(".")); - let val = val.to_str(); +pub fn pn_children(pth: MaybeString, with_dir: MaybeBoolean) -> Result<AnyObject, Exception> { + let path = pth.unwrap_or(RString::new(".")); + let path = path.to_str(); - if let Ok(entries) = fs::read_dir(val) { - let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool(); - if val == "." { + if let Ok(entries) = fs::read_dir(path) { + let mut with_directory = with_dir.unwrap_or(Boolean::new(true)).to_bool(); + if path == "." { with_directory = false; } - let mut arr = Array::new(); + let mut arr = Array::with_capacity(entries.size_hint().1.unwrap_or(0)); for entry in entries { if with_directory { match entry { Ok(v) => { arr.push(RString::new(v.path().to_str().unwrap())); }, _ => {} @@ -163,29 +156,27 @@ _ => {} }; } } - arr.to_any_object() + Ok(arr.to_any_object()) } else { - // TODO: When ruru exceptions are available switch the exception logic - // from the Ruby side to the Rust side - NilClass::new().to_any_object() + let msg = format!("No such file or directory @ dir_initialize - {}", path); + Err(Exception::new("Errno::NOENT", Some(&msg))) } } -pub fn pn_children_compat(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject { - let val = pth.ok().unwrap_or(RString::new(".")); - let val = val.to_str(); +pub fn pn_children_compat(pth: MaybeString, with_dir: MaybeBoolean) -> Result<AnyObject, Exception> { + let path = to_str(&pth); - if let Ok(entries) = fs::read_dir(val) { - let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool(); - if val == "." { + if let Ok(entries) = fs::read_dir(path) { + let mut with_directory = with_dir.unwrap_or(Boolean::new(true)).to_bool(); + if path == "." { with_directory = false; } - let mut arr = Array::new(); + let mut arr = Array::with_capacity(entries.size_hint().1.unwrap_or(0)); for entry in entries { if with_directory { if let Ok(v) = entry { arr.push(Pathname::new(v.path().to_str().unwrap())); }; @@ -194,148 +185,120 @@ arr.push(Pathname::new(v.file_name().to_str().unwrap())); }; } } - arr.to_any_object() + Ok(arr.to_any_object()) } else { - // TODO: When ruru exceptions are available switch the exception logic - // from the Ruby side to the Rust side - NilClass::new().to_any_object() + let msg = format!("No such file or directory @ dir_initialize - {}", path); + Err(Exception::new("Errno::NOENT", Some(&msg))) } } -pub fn pn_chop_basename(pth: MaybeString) -> Array { - let mut arr = Array::with_capacity(2); - let pth = pth.ok().unwrap_or(RString::new("")); - let results = chop_basename::chop_basename(pth.to_str()); - match results { +pub fn pn_chop_basename(pth: MaybeString) -> AnyObject { + match chop_basename::chop_basename(to_str(&pth)) { Some((dirname, basename)) => { - arr.push(RString::new(&dirname[..])); - arr.push(RString::new(&basename[..])); - arr + let mut arr = Array::with_capacity(2); + arr.push(RString::new(&dirname)); + arr.push(RString::new(&basename)); + arr.to_any_object() }, - None => arr + None => NilClass::new().to_any_object() } } // pub fn pn_cleanpath(pth: MaybeString){} pub fn pn_cleanpath_aggressive(pth: MaybeString) -> RString { - let path = cleanpath_aggressive::cleanpath_aggressive( - pth.ok().unwrap_or(RString::new("")).to_str() - ); - - RString::new(&path) + RString::new(&cleanpath_aggressive::cleanpath_aggressive(to_str(&pth))) } pub fn pn_cleanpath_conservative(pth: MaybeString) -> RString { - let path = cleanpath_conservative::cleanpath_conservative( - pth.ok().unwrap_or(RString::new("")).to_str() - ); - - RString::new(&path) + RString::new(&cleanpath_conservative::cleanpath_conservative(to_str(&pth))) } pub fn pn_del_trailing_separator(pth: MaybeString) -> RString { - if let &Ok(ref path) = &pth { - let path = path.to_str(); - - if !path.is_empty() { - let path = path.trim_right_matches('/'); - - if path.is_empty() { - return RString::new("/"); - } else { - return RString::new(path); - } + { + let path = to_str(&pth); + if path.is_empty() { + return RString::new("/"); } - } else { - return RString::new(""); + let pos = match find_last_non_sep_pos(path.as_bytes()) { + Some(pos) => pos, + None => return RString::new("/"), + }; + if pos != path.len() - 1 { + return RString::new(&path[..pos + 1]); + } } - pth.unwrap() } // pub fn pn_descend(){} pub fn pn_is_directory(pth: MaybeString) -> Boolean { - Boolean::new( - Path::new( - pth.ok().unwrap_or(RString::new("")).to_str() - ).is_dir() - ) + Boolean::new(Path::new(to_str(&pth)).is_dir()) } pub fn pn_dirname(pth: MaybeString) -> RString { - RString::new( - dirname::dirname( - pth.ok().unwrap_or(RString::new("")).to_str() - ) - ) + RString::new(dirname::dirname(to_str(&pth))) } // pub fn pn_each_child(){} // pub fn pn_each_filename(pth: MaybeString) -> NilClass { // NilClass::new() // } -pub fn pn_entries(pth: MaybeString) -> AnyObject { - if let Ok(files) = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()) { - let mut arr = Array::new(); +pub fn pn_entries(pth: MaybeString) -> Result<AnyObject, Exception> { + let path = to_str(&pth); + if let Ok(files) = fs::read_dir(path) { + let mut arr = Array::with_capacity(files.size_hint().1.unwrap_or(0) + 2); arr.push(RString::new(".")); arr.push(RString::new("..")); for file in files { - let file_name_str = file.unwrap().file_name().into_string().unwrap(); - arr.push(RString::new(&file_name_str[..])); + arr.push(RString::new(file.unwrap().file_name().to_str().unwrap())); } - arr.to_any_object() + Ok(arr.to_any_object()) } else { - // TODO: When ruru exceptions are available switch the exception logic - // from the Ruby side to the Rust side - NilClass::new().to_any_object() + let msg = format!("No such file or directory @ dir_initialize - {}", path); + Err(Exception::new("Errno::NOENT", Some(&msg))) } } -pub fn pn_entries_compat(pth: MaybeString) -> AnyObject { - if let Ok(files) = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()) { - let mut arr = Array::new(); +pub fn pn_entries_compat(pth: MaybeString) -> Result<AnyObject, Exception> { + let path = to_str(&pth); + if let Ok(files) = fs::read_dir(path) { + let mut arr = Array::with_capacity(files.size_hint().1.unwrap_or(0) + 2); arr.push(Pathname::new(".")); arr.push(Pathname::new("..")); for file in files { - let file_name_str = file.unwrap().file_name().into_string().unwrap(); - arr.push(Pathname::new(&file_name_str)); + arr.push(Pathname::new(file.unwrap().file_name().to_str().unwrap())); } - arr.to_any_object() + Ok(arr.to_any_object()) } else { - // TODO: When ruru exceptions are available switch the exception logic - // from the Ruby side to the Rust side - NilClass::new().to_any_object() + let msg = format!("No such file or directory @ dir_initialize - {}", path); + Err(Exception::new("Errno::NOENT", Some(&msg))) } } pub fn pn_extname(pth: MaybeString) -> RString { - RString::new( - extname::extname(pth.ok().unwrap_or(RString::new("")).to_str()) - ) + RString::new(extname::extname(to_str(&pth))) } // pub fn pn_find(pth: MaybeString, ignore_error: Boolean){} pub fn pn_has_trailing_separator(pth: MaybeString) -> 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()) - }, + let v = to_str(&pth); + match chop_basename::chop_basename(v) { + Some((a,b)) => Boolean::new(a.len() + b.len() < v.len()), _ => Boolean::new(false) } } pub fn pn_join(args: MaybeArray) -> AnyObject { @@ -351,17 +314,17 @@ loop { if qty == 0 { break; } let item = args.pop(); result = plus::plus_paths(&anyobject_to_string(item).unwrap(), &result); - if result.chars().next() == Some(MAIN_SEPARATOR) { + if result.as_bytes().get(0) == Some(&SEP) { return Pathname::new(&result).to_any_object() } qty -= 1; } - + let result = plus::plus_paths(&path_self, &result); Pathname::new(&result).to_any_object() } @@ -372,26 +335,20 @@ // pub fn pn_is_mountpoint(pth: MaybeString){} // pub fn pn_parent(pth: MaybeString){} pub fn pn_plus(pth1: MaybeString, pth2: MaybeString) -> RString { - RString::new( - &plus::plus_paths( - pth1.ok().unwrap_or(RString::new("")).to_str(), - pth2.ok().unwrap_or(RString::new("")).to_str() - )[..] - ) + RString::new(&plus::plus_paths(to_str(&pth1), to_str(&pth2))) } // pub fn pn_prepend_prefix(prefix: MaybeString, relpath: MaybeString){} pub fn pn_is_relative(pth: MaybeString) -> 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 - } - ) + let path = match &pth { + &Ok(ref ruru_string) => ruru_string.to_str(), + &Err(_) => return Boolean::new(false), + }; + Boolean::new(path.as_bytes().get(0) != Some(&SEP)) } // pub fn pn_root(pth: MaybeString){} // pub fn pn_split_names(pth: MaybeString){}