use crate::decompression::read_crc32_block;
use crate::error::{PluginError, Result, ValidationError};
use crate::plugin::registry::get_plugin_by_magic;
use crate::plugin::{CrushHeader, FileMetadata};
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct InspectResult {
pub original_size: u64,
pub compressed_size: u64,
pub plugin_name: String,
pub crc_valid: bool,
pub metadata: FileMetadata,
}
pub fn inspect(input: &[u8]) -> Result<InspectResult> {
if input.len() < CrushHeader::SIZE {
return Err(ValidationError::InvalidHeader(format!(
"Input too short: {} bytes, expected at least {}",
input.len(),
CrushHeader::SIZE
))
.into());
}
let header_bytes: [u8; CrushHeader::SIZE] = input[0..CrushHeader::SIZE]
.try_into()
.map_err(|_| ValidationError::InvalidHeader("Failed to read header".to_string()))?;
let header = CrushHeader::from_bytes(&header_bytes)?;
let mut payload_start = CrushHeader::SIZE;
let mut crc_valid = false;
if header.has_crc32() {
let (stored_crc, computed_crc, new_start) = read_crc32_block(input, payload_start)?;
payload_start = new_start;
crc_valid = stored_crc == computed_crc;
}
let metadata = if header.has_metadata() {
if input.len() < payload_start + 2 {
return Err(ValidationError::InvalidHeader(
"Truncated: metadata flag set but no metadata length".to_string(),
)
.into());
}
let metadata_len =
u16::from_le_bytes([input[payload_start], input[payload_start + 1]]) as usize;
payload_start += 2;
if input.len() < payload_start + metadata_len {
return Err(ValidationError::InvalidHeader(
"Truncated: metadata length exceeds payload size".to_string(),
)
.into());
}
let metadata_bytes = &input[payload_start..payload_start + metadata_len];
FileMetadata::from_bytes(metadata_bytes)?
} else {
FileMetadata::default()
};
let plugin = get_plugin_by_magic(header.magic).ok_or_else(|| {
PluginError::NotFound(format!(
"No plugin found for magic number {:02X?}",
header.magic
))
})?;
Ok(InspectResult {
original_size: header.original_size,
compressed_size: input.len() as u64,
plugin_name: plugin.name().to_string(),
crc_valid,
metadata,
})
}