asar 0.2.0

A crate to read and write asar archives, often used by Electron apps.
Documentation
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::header::HashAlgorithm;
use sha2::{
	digest::{typenum::Unsigned, Digest, OutputSizeUser},
	Sha256,
};

impl HashAlgorithm {
	/// Returns the length of the output of the hash function.
	///
	/// ## Example
	/// ```rust
	/// use asar::HashAlgorithm;
	///
	/// assert_eq!(HashAlgorithm::Sha256.hash_len(), 32);
	/// ```
	pub const fn hash_len(&self) -> usize {
		match self {
			HashAlgorithm::Sha256 => <Sha256 as OutputSizeUser>::OutputSize::USIZE,
		}
	}

	/// Hashes the given data and returns the hash.
	///
	/// ## Example
	/// ```rust
	/// use asar::HashAlgorithm;
	///
	/// let data = b"A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.";
	/// let hash = HashAlgorithm::Sha256.hash(data);
	/// assert_eq!(hash, b"\x4f\x71\x68\x29\xf5\xd2\x95\xcb\x1a\x24\x33\xb5\x99\x39\xa3\xcf\xf7\x77\x2a\x9c\xb9\x13\x2c\x63\xbe\x56\x10\xfe\x52\x08\x65\x90");
	/// ```
	pub fn hash(&self, data: &[u8]) -> Vec<u8> {
		match self {
			Self::Sha256 => {
				let mut hasher = Sha256::new();
				hasher.update(data);
				hasher.finalize().to_vec()
			}
		}
	}

	/// Splits the given data into blocks of a specific size, and hashes each
	/// block.
	///
	/// ## Example
	/// ```rust
	/// use asar::HashAlgorithm;
	///
	/// let data = "The ships hung in the sky in much the same way that bricks don't.";
	/// let hash = HashAlgorithm::Sha256.hash_blocks(25, data.as_bytes());
	/// assert_eq!(
	/// 	hash,
	/// 	vec![
	/// 		b"\x9d\x84\xeb\x91\x5a\x78\x2c\xc7\x2e\x74\x6d\x41\x62\x59\xe2\x28\xa2\x79\x03\x04\xf7\x6a\xa4\x20\x03\x3c\xf4\x50\xd7\x84\x26\x6c",
	/// 		b"\xdf\x78\xe6\x17\x28\xb6\x61\x8c\x55\x82\xb9\x00\x41\x96\x31\x2c\x24\x85\xe5\x83\xc2\x7b\xba\x8e\x2c\xbb\x1c\x36\x6f\x1a\x73\xad",
	/// 		b"\x7f\xda\x3f\x7b\x0e\x6d\x11\xc0\x61\x23\xff\x52\xd6\x10\xe1\xc3\xa3\xb7\x17\x22\xc0\x8b\xef\x0d\x96\x77\xc0\x46\x1c\x83\xf2\x4e"
	/// 	]
	/// );
	/// ```
	pub fn hash_blocks(&self, block_size: usize, data: &[u8]) -> Vec<Vec<u8>> {
		let mut blocks = Vec::with_capacity((0..data.len()).step_by(block_size).size_hint().0);
		data.chunks(block_size).for_each(|block| {
			let hash = self.hash(block);
			blocks.push(hash);
		});
		blocks
	}
}