use std::io::Read;
use delharc::decode::{Decoder, Lh1Decoder};
use crate::error::{ArchiveError, Result};
pub struct IceArchive {
#[allow(dead_code)]
original_size: u32,
data: Vec<u8>,
}
impl IceArchive {
pub fn original_size(&self) -> u32 {
self.original_size
}
pub fn new<T: Read>(mut reader: T) -> Result<Self> {
let mut file_data = Vec::new();
reader.read_to_end(&mut file_data)?;
if file_data.len() < 4 {
return Err(ArchiveError::invalid_header("ICE"));
}
let original_size = u32::from_le_bytes(file_data[0..4].try_into().unwrap());
let compressed_data = &file_data[4..];
let data = Self::try_decompress(compressed_data, original_size)?;
Ok(Self { original_size, data })
}
fn try_decompress(compressed: &[u8], expected_size: u32) -> Result<Vec<u8>> {
if let Ok(data) = Self::decompress_lh1(compressed, expected_size) {
return Ok(data);
}
Err(crate::error::ArchiveError::decompression_failed(
"ICE",
"Failed to decompress with any supported LHA method",
))
}
fn decompress_lh1(compressed: &[u8], expected_size: u32) -> Result<Vec<u8>> {
let cursor = std::io::Cursor::new(compressed);
let mut decoder = Lh1Decoder::new(cursor);
let mut decompressed = vec![0u8; expected_size as usize];
decoder
.fill_buffer(&mut decompressed)
.map_err(|e| crate::error::ArchiveError::decompression_failed("ICE", format!("{:?}", e)))?;
if decompressed.len() as u32 != expected_size {
return Err(crate::error::ArchiveError::corrupted_entry(
"ICE",
"Decompressed size does not match expected size",
));
}
Ok(decompressed)
}
pub fn skip(&mut self) -> Result<()> {
Ok(())
}
pub fn read(&mut self) -> Result<Vec<u8>> {
Ok(std::mem::take(&mut self.data))
}
}