118 lines
3.4 KiB
Rust
118 lines
3.4 KiB
Rust
use {
|
|
crate::{Checksum, Error},
|
|
md5::{Digest, Md5},
|
|
sha1::Sha1,
|
|
sha2::Sha256,
|
|
std::io::{Read, Write},
|
|
};
|
|
|
|
/// A representation of a regular file as an archive member
|
|
#[derive(Debug)]
|
|
pub struct File {
|
|
/// The length of this file
|
|
pub len: u64,
|
|
/// The optional checksum of this file
|
|
pub checksum: Checksum,
|
|
/// The bytes making up this file
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
impl File {
|
|
pub(crate) 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_to_end(&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)
|
|
}
|
|
}
|
|
Checksum::Skip => Ok(Self {
|
|
len,
|
|
checksum,
|
|
data,
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
|
|
writer.write_all(&self.len.to_le_bytes())?;
|
|
Checksum::write(&self.checksum, writer)?;
|
|
writer.write_all(&self.data)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::fs::File as Fd;
|
|
|
|
const SHA1BUF: [u8; 20] = [
|
|
155, 243, 229, 181, 239, 210, 47, 147, 46, 16, 11, 134, 200, 52, 130, 120, 126, 130, 166,
|
|
130,
|
|
];
|
|
|
|
#[test]
|
|
fn load_store() {
|
|
let file = File {
|
|
len: 1005,
|
|
checksum: Checksum::Sha1(SHA1BUF),
|
|
data: include_bytes!("../test/li.txt").to_vec(),
|
|
};
|
|
{
|
|
let mut fd = Fd::create("test/file").unwrap();
|
|
file.write(&mut fd).unwrap();
|
|
}
|
|
let mut fd = Fd::open("test/file").unwrap();
|
|
let res = File::read(&mut fd).unwrap();
|
|
assert_eq!(file.len, res.len);
|
|
assert_eq!(&file.data, &res.data);
|
|
match res.checksum {
|
|
Checksum::Sha1(sum) => assert_eq!(sum, SHA1BUF),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|