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, } impl File { pub fn read(reader: &mut T) -> Result { 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(&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(()) } }