use std::num::ParseIntError;
use chksum::hash::HashAlgorithm;
use thiserror::Error;
#[derive(Debug, Eq, Error, PartialEq)]
pub(crate) enum Error {
#[error("Not a valid number")]
ChunkSizeIsNotANumber(#[from] ParseIntError),
#[error("Value is zero")]
ChunkSizeIsZero,
#[error("Unknown suffix `{0}`")]
ChunkSizeUnknownSuffix(String),
#[error("Unknown hash Algorithm")]
HashAlgorithmUnknown,
}
pub(crate) fn hash<T>(value: T) -> Result<HashAlgorithm, Error>
where
T: AsRef<str>,
{
let value = value.as_ref();
match value {
"MD5" => Ok(HashAlgorithm::MD5),
"SHA1" | "SHA-1" => Ok(HashAlgorithm::SHA1),
"SHA224" | "SHA-224" | "SHA2 224" | "SHA-2 224" => Ok(HashAlgorithm::SHA2_224),
"SHA256" | "SHA-256" | "SHA2 256" | "SHA-2 256" => Ok(HashAlgorithm::SHA2_256),
"SHA384" | "SHA-384" | "SHA2 384" | "SHA-2 384" => Ok(HashAlgorithm::SHA2_384),
"SHA512" | "SHA-512" | "SHA2 512" | "SHA-2 512" => Ok(HashAlgorithm::SHA2_512),
_ => Err(Error::HashAlgorithmUnknown),
}
}
pub(crate) fn human_number<T>(value: T) -> Result<usize, Error>
where
T: AsRef<str>,
{
let value = value.as_ref();
let value = if let Ok(value) = value.parse::<usize>() {
value
} else {
let length = value.len();
let (value, suffix) = value.split_at(length - 1);
let value = value.parse::<usize>()?;
let multiply = match suffix {
"k" | "K" => Some(1024),
"m" | "M" => Some(1024 * 1024),
"g" | "G" => Some(1024 * 1024 * 1024),
_ => None,
};
let multiply = multiply.ok_or_else(|| Error::ChunkSizeUnknownSuffix(suffix.to_owned()))?;
value * multiply
};
match value {
_ if value > 0 => Ok(value),
_ => Err(Error::ChunkSizeIsZero),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_md5() {
assert!(
matches!(hash("MD5"), Ok(HashAlgorithm::MD5)),
"string is a valid MD5 name!"
);
assert!(
matches!(hash("md5"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid MD5 name!"
);
assert!(
matches!(hash("Md5"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid MD5 name!"
);
assert!(
matches!(hash("MD 5"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid MD5 name!"
);
}
#[test]
fn test_hash_sha1() {
assert!(
matches!(hash("SHA1"), Ok(HashAlgorithm::SHA1)),
"string is a valid SHA-1 name!"
);
assert!(
matches!(hash("SHA-1"), Ok(HashAlgorithm::SHA1)),
"string is a valid SHA-1 name!"
);
assert!(
matches!(hash("sha1"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-1 name!"
);
assert!(
matches!(hash("Sha1"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-1 name!"
);
assert!(
matches!(hash("SHA 1"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-1 name!"
);
}
#[test]
fn test_hash_sha2_224() {
assert!(
matches!(hash("SHA224"), Ok(HashAlgorithm::SHA2_224)),
"string is a valid SHA-2 224 name!"
);
assert!(
matches!(hash("SHA-224"), Ok(HashAlgorithm::SHA2_224)),
"string is a valid SHA-2 224 name!"
);
assert!(
matches!(hash("SHA2 224"), Ok(HashAlgorithm::SHA2_224)),
"string is a valid SHA-2 224 name!"
);
assert!(
matches!(hash("SHA-2 224"), Ok(HashAlgorithm::SHA2_224)),
"string is a valid SHA-2 224 name!"
);
assert!(
matches!(hash("sha224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
assert!(
matches!(hash("Sha224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
assert!(
matches!(hash("SHA 224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
assert!(
matches!(hash("sha2 224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
assert!(
matches!(hash("Sha2 224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
assert!(
matches!(hash("SHA 2 224"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 224 name!"
);
}
#[test]
fn test_hash_sha2_256() {
assert!(
matches!(hash("SHA256"), Ok(HashAlgorithm::SHA2_256)),
"string is a valid SHA-2 256 name!"
);
assert!(
matches!(hash("SHA-256"), Ok(HashAlgorithm::SHA2_256)),
"string is a valid SHA-2 256 name!"
);
assert!(
matches!(hash("SHA2 256"), Ok(HashAlgorithm::SHA2_256)),
"string is a valid SHA-2 256 name!"
);
assert!(
matches!(hash("SHA-2 256"), Ok(HashAlgorithm::SHA2_256)),
"string is a valid SHA-2 256 name!"
);
assert!(
matches!(hash("sha256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
assert!(
matches!(hash("Sha256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
assert!(
matches!(hash("SHA 256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
assert!(
matches!(hash("sha2 256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
assert!(
matches!(hash("Sha2 256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
assert!(
matches!(hash("SHA 2 256"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 name!"
);
}
#[test]
fn test_hash_sha2_384() {
assert!(
matches!(hash("SHA384"), Ok(HashAlgorithm::SHA2_384)),
"string is a valid SHA-2 384 name!"
);
assert!(
matches!(hash("SHA-384"), Ok(HashAlgorithm::SHA2_384)),
"string is a valid SHA-2 384 name!"
);
assert!(
matches!(hash("SHA2 384"), Ok(HashAlgorithm::SHA2_384)),
"string is a valid SHA-2 384 name!"
);
assert!(
matches!(hash("SHA-2 384"), Ok(HashAlgorithm::SHA2_384)),
"string is a valid SHA-2 384 name!"
);
assert!(
matches!(hash("sha384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 256 n384!"
);
assert!(
matches!(hash("Sha384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 384 name!"
);
assert!(
matches!(hash("SHA 384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 384 name!"
);
assert!(
matches!(hash("sha2 384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 384 name!"
);
assert!(
matches!(hash("Sha2 384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 384 name!"
);
assert!(
matches!(hash("SHA 2 384"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 384 name!"
);
}
#[test]
fn test_hash_sha2_512() {
assert!(
matches!(hash("SHA512"), Ok(HashAlgorithm::SHA2_512)),
"string is a valid SHA-2 512 name!"
);
assert!(
matches!(hash("SHA-512"), Ok(HashAlgorithm::SHA2_512)),
"string is a valid SHA-2 512 name!"
);
assert!(
matches!(hash("SHA2 512"), Ok(HashAlgorithm::SHA2_512)),
"string is a valid SHA-2 512 name!"
);
assert!(
matches!(hash("SHA-2 512"), Ok(HashAlgorithm::SHA2_512)),
"string is a valid SHA-2 512 name!"
);
assert!(
matches!(hash("sha512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
assert!(
matches!(hash("Sha512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
assert!(
matches!(hash("SHA 512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
assert!(
matches!(hash("sha2 512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
assert!(
matches!(hash("Sha2 512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
assert!(
matches!(hash("SHA 2 512"), Err(Error::HashAlgorithmUnknown)),
"string is not a valid SHA-2 512 name!"
);
}
#[test]
fn test_human_number() {
assert!(
matches!(human_number("2"), Ok(human_number) if human_number == 2),
"chunk size is valid"
);
assert!(
matches!(human_number("16"), Ok(human_number) if human_number == 16),
"chunk size is valid"
);
assert!(
matches!(human_number("512"), Ok(human_number) if human_number == 512),
"chunk size is valid"
);
assert!(
matches!(human_number("1k"), Ok(human_number) if human_number == 1 * 1024),
"chunk size is valid"
);
assert!(
matches!(human_number("2K"), Ok(human_number) if human_number == 2 * 1024),
"chunk size is valid"
);
assert!(
matches!(human_number("4m"), Ok(human_number) if human_number == 4 * 1024 * 1024),
"chunk size is valid"
);
assert!(
matches!(human_number("8M"), Ok(human_number) if human_number == 8 * 1024 * 1024),
"chunk size is valid"
);
#[cfg(target_pointer_width = "32")]
assert!(
matches!(human_number("1g"), Ok(human_number) if human_number == 1 * 1024 * 1024 * 1024),
"chunk size is valid"
);
#[cfg(target_pointer_width = "64")]
assert!(
matches!(human_number("16g"), Ok(human_number) if human_number == 16 * 1024 * 1024 * 1024),
"chunk size is valid"
);
#[cfg(target_pointer_width = "32")]
assert!(
matches!(human_number("2G"), Ok(human_number) if human_number == 2 * 1024 * 1024 * 1024),
"chunk size is valid"
);
#[cfg(target_pointer_width = "64")]
assert!(
matches!(human_number("32G"), Ok(human_number) if human_number == 32 * 1024 * 1024 * 1024),
"chunk size is valid"
);
assert!(
matches!(human_number("0"), Err(Error::ChunkSizeIsZero)),
"chunk size is zero!"
);
assert!(
matches!(human_number("0k"), Err(Error::ChunkSizeIsZero)),
"chunk size is zero!"
);
assert!(
matches!(human_number("0M"), Err(Error::ChunkSizeIsZero)),
"chunk size is zero!"
);
assert!(
matches!(human_number("0g"), Err(Error::ChunkSizeIsZero)),
"chunk size is zero!"
);
assert!(
matches!(human_number("0x0"), Err(Error::ChunkSizeIsNotANumber(_))),
"chunk size is not a number!"
);
assert!(
matches!(human_number("0x0g"), Err(Error::ChunkSizeIsNotANumber(_))),
"chunk size is not a number!"
);
assert!(
matches!(human_number("abc"), Err(Error::ChunkSizeIsNotANumber(_))),
"chunk size is not a number!"
);
assert!(
matches!(human_number("15x"), Err(Error::ChunkSizeUnknownSuffix(_))),
"suffix is unknown!"
);
assert!(
matches!(human_number("15 "), Err(Error::ChunkSizeUnknownSuffix(_))),
"suffix is unknown!"
);
}
}