use crate::io::ReadSeek;
use crate::DiskImageError;
use std::io::Read;
use std::path::Path;
#[allow(dead_code)]
pub struct ZipFileEntry {
pub name: String,
pub size: u64,
}
#[allow(dead_code)]
pub struct ZipFileListing {
pub files: Vec<ZipFileEntry>,
pub total_size: u64,
}
pub fn detect_zip<T: ReadSeek>(image_io: &mut T) -> (bool, usize, u64) {
match zip::ZipArchive::new(image_io) {
Ok(zip) => (true, zip.len(), zip.decompressed_size().unwrap_or(0) as u64),
Err(_) => (false, 0, 0),
}
}
#[allow(dead_code)]
pub fn file_ct<T: ReadSeek>(image_io: &mut T) -> Result<usize, DiskImageError> {
let zip = zip::ZipArchive::new(image_io).map_err(|_| DiskImageError::FormatParseError)?;
Ok(zip.len())
}
pub fn file_listing<T: ReadSeek>(image_io: &mut T) -> Result<ZipFileListing, DiskImageError> {
let mut zip = zip::ZipArchive::new(image_io).map_err(|_| DiskImageError::FormatParseError)?;
let mut files = Vec::new();
let mut total_size = 0;
for i in 0..zip.len() {
let file = zip.by_index(i).map_err(|_| DiskImageError::FormatParseError)?;
if let Some(file_name) = file.enclosed_name() {
files.push(ZipFileEntry {
name: file_name.to_string_lossy().to_string(),
size: file.size(),
});
total_size += file.size();
}
}
Ok(ZipFileListing { files, total_size })
}
pub fn extract_file<T: ReadSeek>(image_io: &mut T, file_name: &Path) -> Result<Vec<u8>, DiskImageError> {
let mut zip = zip::ZipArchive::new(image_io).map_err(|_| DiskImageError::FormatParseError)?;
let mut file = zip
.by_name(&file_name.to_string_lossy())
.map_err(|_| DiskImageError::FormatParseError)?;
if file.size() > 100_000_000 {
return Err(DiskImageError::IoError("File too large".to_string()));
}
let mut file_buf = Vec::new();
file.read_to_end(&mut file_buf)?;
Ok(file_buf)
}
pub fn extract_first_file<T: ReadSeek>(image_io: &mut T) -> Result<Vec<u8>, DiskImageError> {
let mut zip = zip::ZipArchive::new(image_io).map_err(|_| DiskImageError::FormatParseError)?;
if zip.is_empty() {
return Err(DiskImageError::FormatParseError);
}
let mut file = zip.by_index(0).map_err(|_| DiskImageError::FormatParseError)?;
if file.size() > 100_000_000 {
return Err(DiskImageError::IoError("File too large".to_string()));
}
let mut file_buf = Vec::new();
file.read_to_end(&mut file_buf)?;
Ok(file_buf)
}