use crate::csaf::traits::util::impl_str_field_getter;
use crate::csaf::types::csaf_hash_algo::CsafHashAlgorithm;
use crate::csaf_traits::FileHashTrait;
use crate::schema::csaf2_0::schema::{CryptographicHashes as CryptographicHashes20, FileHash as FileHash20};
use crate::schema::csaf2_1::schema::{CryptographicHashes as CryptographicHashes21, FileHash as FileHash21};
pub trait HashTrait {
type FileHashType: FileHashTrait;
fn get_filename(&self) -> &str;
fn get_file_hashes(&self) -> &Vec<Self::FileHashType>;
fn contains_only_hash_algorithm(&self, algorithm: CsafHashAlgorithm) -> bool {
let file_hashes = self.get_file_hashes();
if file_hashes.is_empty() {
return false;
}
file_hashes.iter().all(|h| h.get_algorithm().normalize() == algorithm)
}
}
impl HashTrait for CryptographicHashes20 {
type FileHashType = FileHash20;
impl_str_field_getter!(get_filename, filename);
fn get_file_hashes(&self) -> &Vec<Self::FileHashType> {
self.file_hashes.as_ref()
}
}
impl HashTrait for CryptographicHashes21 {
type FileHashType = FileHash21;
impl_str_field_getter!(get_filename, filename);
fn get_file_hashes(&self) -> &Vec<Self::FileHashType> {
self.file_hashes.as_ref()
}
}
#[cfg(test)]
mod tests_contains_only_hash_algorithm {
use super::*;
use CsafHashAlgorithm::*;
use rstest::rstest;
struct MockFileHash(CsafHashAlgorithm);
impl FileHashTrait for MockFileHash {
fn get_hash(&self) -> &str {
unimplemented!()
}
fn get_algorithm(&self) -> CsafHashAlgorithm {
self.0.clone()
}
}
struct MockCryptographicHashes {
file_hashes: Vec<MockFileHash>,
}
impl MockCryptographicHashes {
fn new(algos: &[CsafHashAlgorithm]) -> Self {
Self {
file_hashes: algos.iter().map(|a| MockFileHash(a.clone())).collect(),
}
}
}
impl HashTrait for MockCryptographicHashes {
type FileHashType = MockFileHash;
fn get_filename(&self) -> &str {
unimplemented!()
}
fn get_file_hashes(&self) -> &Vec<MockFileHash> {
&self.file_hashes
}
}
#[rstest]
#[case(&[Md5], Md5)]
#[case(&[Sha1], Sha1)]
#[case(&[Md5, Md5], Md5)]
#[case(&[Sha1, Sha1, Sha1], Sha1)]
fn returns_true(#[case] algos: &[CsafHashAlgorithm], #[case] expected: CsafHashAlgorithm) {
let mock = MockCryptographicHashes::new(algos);
assert!(mock.contains_only_hash_algorithm(expected));
}
#[rstest]
#[case(&[], Md5)]
#[case(&[Md5], Sha1)]
#[case(&[Md5, Sha256], Md5)]
#[case(&[Md5, Sha1, Sha256], Sha1)]
#[case(&[Md5, Sha256], Sha1)]
fn returns_false(#[case] algos: &[CsafHashAlgorithm], #[case] expected: CsafHashAlgorithm) {
let mock = MockCryptographicHashes::new(algos);
assert!(!mock.contains_only_hash_algorithm(expected));
}
}