use std::path::Path;
use super::errors::FinderError;
use super::options::Options;
#[derive(Clone, Debug, Default)]
pub struct Finder {
opts: Options,
}
impl Finder {
pub fn new() -> Finder {
Finder {
opts: Options::default(),
}
}
pub fn options(&self) -> &Options {
&self.opts
}
pub fn options_mut(&mut self) -> &mut Options {
&mut self.opts
}
pub fn add_path<'a>(&'a mut self, path: &str) -> &'a mut Finder {
self.opts.add_path(path);
self
}
pub fn add_paths(&mut self, paths: &[String]) -> &mut Finder {
self.opts.set_paths(paths.to_vec());
self
}
pub fn find(&self, filename: &str) -> Result<String, FinderError> {
find_file(filename, &self.opts)
}
}
pub fn find_file(filename: &str, opts: &Options) -> Result<String, FinderError> {
let path = Path::new(filename);
if path.exists() {
return path
.to_str()
.ok_or_else(|| FinderError::PathConversion(filename.to_string()))
.map(|s| s.to_string());
}
for search_path in opts.paths().iter() {
let file = Path::new(search_path).join(filename);
if file.exists() {
return file
.to_str()
.ok_or_else(|| FinderError::PathConversion(file.to_string_lossy().into_owned()))
.map(|s| s.to_string());
}
}
Err(FinderError::NotFound(filename.to_string()))
}