use crate::{
chs::DiskChs,
containers::{zip, DiskImageContainer},
file_parsers::{kryoflux::KfxFormat, ImageParser, IMAGE_FORMATS},
};
use crate::{
containers::KryoFluxSet,
io::ReadSeek,
standard_format::StandardFormat,
util::natural_sort,
DiskImageError,
DiskImageFileFormat,
};
use std::path::PathBuf;
pub fn detect_image_format<T: ReadSeek>(image_io: &mut T) -> Result<DiskImageContainer, DiskImageError> {
#[cfg(feature = "zip")]
{
let (is_zip, file_ct, total_size) = zip::detect_zip(image_io);
if is_zip & (file_ct > 0) {
log::debug!("ZIP file detected with {} files, total size: {}", file_ct, total_size);
if file_ct == 1 {
let file_buf = match zip::extract_first_file(image_io) {
Ok(buf) => buf,
Err(e) => return Err(e),
};
let mut file_io = std::io::Cursor::new(file_buf);
for format in IMAGE_FORMATS.iter() {
if format.detect(&mut file_io) {
return Ok(DiskImageContainer::Zip(*format));
}
}
return Err(DiskImageError::UnknownFormat);
}
else if total_size > 5_000_000 {
let zip_listing = zip::file_listing(image_io)?;
let path_vec: Vec<PathBuf> = zip_listing
.files
.iter()
.map(|entry| PathBuf::from(&entry.name))
.collect();
let mut raw_files: Vec<_> = path_vec
.iter()
.filter(|&path| {
path.file_name()
.and_then(|name| name.to_str())
.map_or(false, |name| name.ends_with("00.0.raw"))
})
.collect();
raw_files.sort_by(|a: &&PathBuf, b: &&PathBuf| natural_sort(a, b));
log::warn!("raw files: {:?}", raw_files);
let mut set_vec = Vec::new();
for file in raw_files {
log::debug!("Found .raw file in zip: {:?}", file);
let kryo_set = KfxFormat::expand_kryoflux_set(file.clone(), Some(path_vec.clone()))?;
log::debug!(
"Expanded to kryoflux set of {} files, geometry: {}",
kryo_set.0.len(),
kryo_set.1
);
let path_to_set = file.parent().unwrap_or(&PathBuf::new()).to_path_buf();
set_vec.push(KryoFluxSet {
base_path: path_to_set.clone(),
file_set: kryo_set.0,
geometry: kryo_set.1,
});
}
if !set_vec.is_empty() {
for (si, set) in set_vec.iter().enumerate() {
log::debug!(
"Found Kryoflux set in archive at idx {}, path : {}",
si,
set.base_path.display()
);
}
return Ok(DiskImageContainer::ZippedKryofluxSet(set_vec));
}
}
}
}
for format in IMAGE_FORMATS.iter() {
if format.detect(&mut *image_io) {
if let DiskImageFileFormat::KryofluxStream = format {
return Ok(DiskImageContainer::KryofluxSet);
}
return Ok(DiskImageContainer::Raw(*format));
}
}
Err(DiskImageError::UnknownFormat)
}
pub fn chs_from_raw_size(size: usize) -> Option<DiskChs> {
let raw_size_fmt = StandardFormat::from(size);
if raw_size_fmt != StandardFormat::Invalid {
return Some(raw_size_fmt.get_chs());
}
None
}