2023-07-04 00:51:47 -04:00
|
|
|
use {
|
|
|
|
crate::{Checksum, Error},
|
|
|
|
md5::{Digest, Md5},
|
|
|
|
sha1::Sha1,
|
|
|
|
sha2::Sha256,
|
|
|
|
std::io::{Read, Write},
|
|
|
|
};
|
|
|
|
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A representation of a regular file as an archive member
|
2023-07-04 00:51:47 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct File {
|
2023-07-04 20:13:38 -04:00
|
|
|
/// The length of this file
|
2023-07-04 00:51:47 -04:00
|
|
|
pub len: u64,
|
2023-07-04 20:13:38 -04:00
|
|
|
/// The optional checksum of this file
|
2023-07-04 00:51:47 -04:00
|
|
|
pub checksum: Checksum,
|
2023-07-04 20:13:38 -04:00
|
|
|
/// The bytes making up this file
|
2023-07-04 00:51:47 -04:00
|
|
|
pub data: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl File {
|
|
|
|
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
|
|
|
|
let mut len = [0; 8];
|
|
|
|
reader.read_exact(&mut len)?;
|
|
|
|
let len = u64::from_le_bytes(len);
|
|
|
|
let checksum = Checksum::read(reader)?;
|
|
|
|
let mut data = Vec::with_capacity(len.try_into()?);
|
|
|
|
let mut handle = reader.take(len);
|
|
|
|
handle.read_exact(&mut data)?;
|
|
|
|
match checksum {
|
|
|
|
Checksum::Md5(sum) => {
|
|
|
|
let mut hasher = Md5::new();
|
|
|
|
hasher.update(&data);
|
|
|
|
let res = hasher.finalize();
|
|
|
|
if res == sum.into() {
|
|
|
|
Ok(Self {
|
|
|
|
len,
|
|
|
|
checksum,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(Error::InvalidChecksum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Checksum::Sha1(sum) => {
|
|
|
|
let mut hasher = Sha1::new();
|
|
|
|
hasher.update(&data);
|
|
|
|
let res = hasher.finalize();
|
|
|
|
if res == sum.into() {
|
|
|
|
Ok(Self {
|
|
|
|
len,
|
|
|
|
checksum,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(Error::InvalidChecksum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Checksum::Sha256(sum) => {
|
|
|
|
let mut hasher = Sha256::new();
|
|
|
|
hasher.update(&data);
|
|
|
|
let res = hasher.finalize();
|
|
|
|
if res == sum.into() {
|
|
|
|
Ok(Self {
|
|
|
|
len,
|
|
|
|
checksum,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(Error::InvalidChecksum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Ok(Self {
|
|
|
|
len,
|
|
|
|
checksum,
|
|
|
|
data,
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
|
|
|
|
writer.write_all(&self.len.to_be_bytes())?;
|
|
|
|
Checksum::write(&self.checksum, writer)?;
|
|
|
|
writer.write_all(&self.data)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|