use crate::{ImageFiles, FileLocation, FileProperties, FilePath, FilePathWithMetadata};
use std::ffi::OsStr;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::path::PathBuf;
pub struct ImageFilesBuilder<P: FileProperties, L: FileLocation<P>> {
file_list: Vec<L>,
phantom: PhantomData<P>
}
impl<P: FileProperties, L: FileLocation<P>> Default for ImageFilesBuilder<P, L> {
fn default() -> Self {
Self {
file_list: vec![],
phantom: PhantomData::default()
}
}
}
impl<P, L> ImageFilesBuilder<P, L>
where P: FileProperties + Debug, L: FileLocation<P> + Debug
{
pub fn build(self) -> Result<ImageFiles<P>, String> {
let mut image_files: Vec<P> = vec!();
for file_path in self.file_list.into_iter() {
let properties = file_path.into_properties()?;
image_files.push(properties);
}
Ok(ImageFiles::new(image_files))
}
pub fn add_file(mut self, location: L) -> Result<Self, String> {
let accepted_extensions = ImageFiles::<P>::allowed_extensions();
let file_extension = location.extension()?;
if !Self::extension_in_list(file_extension.as_str(), &accepted_extensions) {
return Err(format!("File not recognised as image file: {:?}", location));
}
if !location.is_file()? {
return Err(format!("Path is not a file: {:?}", location));
}
self.file_list.push(location);
Ok(self)
}
fn extension_in_list(extension: &str, accepted_extensions: &[&str; 5]) -> bool {
accepted_extensions.contains(&extension)
}
}
impl ImageFilesBuilder<FilePathWithMetadata, FilePath> {
pub fn add_current_directory(self, additional_components: Vec<&str>) -> Result<Self, String> {
let current_path = match std::env::current_dir() {
Ok(dir) => dir,
Err(_) => return Err(String::from("Could not access current directory"))
};
if !current_path.is_dir() {
return Err(String::from("Current directory cannot be opened as a directory"));
}
let mut use_path = current_path;
for component in additional_components {
use_path.push(component);
}
self.add_directory(use_path)
}
pub fn add_directory(mut self, source_path: PathBuf) -> Result<Self, String> {
let accepted_extensions = ImageFiles::<FilePathWithMetadata>::allowed_extensions();
let mut image_files: Vec<FilePath> = vec!();
if source_path.is_dir() {
for entry in std::fs::read_dir(source_path).unwrap() {
let path = entry.unwrap().path();
if !path.is_file() {
continue;
}
let stem_not_stitch: Option<()> = (|| {
let file_stem = path
.file_stem()?
.to_str()?;
if file_stem.starts_with("stitch") {
None
} else {
Some(())
}
})();
if stem_not_stitch.is_none() {
continue;
}
let extension = path.extension()
.unwrap_or(OsStr::new(""))
.to_ascii_lowercase();
let lower_str_extension = extension
.to_str()
.unwrap_or("");
if !Self::extension_in_list(lower_str_extension, &accepted_extensions) {
continue;
}
image_files.push(FilePath::new(path));
}
} else {
return Err(
format!("Requested path is not a directory:{}", source_path.to_str().unwrap()));
}
self.file_list.append(&mut image_files);
Ok(self)
}
}