Skip to content

Commit

Permalink
Convert FileDigest to struct to simplify implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
dralley committed Nov 3, 2023
1 parent 2e3463b commit 859e426
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ bitflags! {
// should be equivalent the value mapping used by `pgp::crypto::hash::HashAlgorithm`
// but we have to copy it as not everyone uses the `signature` feature
#[repr(u32)]
#[derive(Debug, Clone, Copy, enum_primitive_derive::Primitive)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, enum_primitive_derive::Primitive)]
pub enum DigestAlgorithm {
Md5 = 1,
Sha2_256 = 8,
Expand Down
53 changes: 22 additions & 31 deletions src/rpm/headers/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,56 +383,47 @@ pub struct FileOwnership {
}

#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub enum FileDigest {
Md5(Vec<u8>),
Sha2_224(Vec<u8>),
Sha2_256(Vec<u8>),
Sha2_384(Vec<u8>),
Sha2_512(Vec<u8>),
// @todo unsupported other types for now
pub struct FileDigest {
digest: String,
algo: DigestAlgorithm,
}

impl FileDigest {
pub fn load_from_str(
pub(crate) fn new(
algorithm: DigestAlgorithm,
stringly_data: impl AsRef<str>,
hex_digest: impl Into<String>,
) -> Result<Self, Error> {
let hex: Vec<u8> = hex::decode(stringly_data.as_ref())?;
let hex = hex_digest.into();
let digest = FileDigest {
digest: hex,
algo: algorithm,
};

Ok(match algorithm {
DigestAlgorithm::Md5 if hex.len() == 16 => FileDigest::Md5(hex),
DigestAlgorithm::Sha2_256 if hex.len() == 32 => FileDigest::Sha2_256(hex),
DigestAlgorithm::Sha2_224 if hex.len() == 30 => FileDigest::Sha2_224(hex),
DigestAlgorithm::Sha2_384 if hex.len() == 48 => FileDigest::Sha2_384(hex),
DigestAlgorithm::Sha2_512 if hex.len() == 64 => FileDigest::Sha2_512(hex),
DigestAlgorithm::Md5 if digest.digest.len() == 32 => digest,
DigestAlgorithm::Sha2_256 if digest.digest.len() == 64 => digest,
DigestAlgorithm::Sha2_224 if digest.digest.len() == 60 => digest,
DigestAlgorithm::Sha2_384 if digest.digest.len() == 96 => digest,
DigestAlgorithm::Sha2_512 if digest.digest.len() == 128 => digest,
// @todo disambiguate mismatch of length from unsupported algorithm
digest_algo => return Err(Error::UnsupportedDigestAlgorithm(digest_algo)),
})
}

/// Return the algorithm that was used for this digest.
pub fn algorithm(&self) -> DigestAlgorithm {
match self {
Self::Md5(_) => DigestAlgorithm::Md5,
Self::Sha2_224(_) => DigestAlgorithm::Sha2_224,
Self::Sha2_256(_) => DigestAlgorithm::Sha2_256,
Self::Sha2_384(_) => DigestAlgorithm::Sha2_384,
Self::Sha2_512(_) => DigestAlgorithm::Sha2_512,
}
self.algo
}

pub fn as_hex(&self) -> String {
match self {
Self::Md5(d) => hex::encode(d),
Self::Sha2_224(d) => hex::encode(d),
Self::Sha2_256(d) => hex::encode(d),
Self::Sha2_384(d) => hex::encode(d),
Self::Sha2_512(d) => hex::encode(d),
}
/// Return the digest
pub fn as_hex(&self) -> &str {
self.digest.as_str()
}
}

impl Display for FileDigest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.as_hex())
f.write_str(self.as_hex())
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/rpm/headers/types.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! A collection of types used in various header records.
use std::str::FromStr;

use crate::{constants::*, errors, Timestamp};
use capctl::FileCaps;
use digest::Digest;
use std::str::FromStr;

/// Offsets into an RPM Package (from the start of the file) demarking locations of each section
///
Expand Down
2 changes: 1 addition & 1 deletion src/rpm/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ impl PackageMetadata {
let digest = if digest.is_empty() {
None
} else {
Some(FileDigest::load_from_str(algorithm, digest)?)
Some(FileDigest::new(algorithm, digest)?)
};
let cap = match caps {
Some(caps) => caps.get(idx).map(|x| x.to_owned()),
Expand Down
8 changes: 6 additions & 2 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,12 @@ fn test_rpm_header() -> Result<(), Box<dyn std::error::Error>> {
let checksums: Vec<_> = metadata
.get_file_entries()?
.iter()
.map(|e| e.digest.as_ref().map(|d| d.to_string()))
.map(|d| d.unwrap_or("".to_owned()))
.map(|e| {
e.digest
.as_ref()
.map(|d| d.to_string())
.unwrap_or("".to_owned())
})
.collect();
assert_eq!(expected_file_checksums, checksums);

Expand Down

0 comments on commit 859e426

Please sign in to comment.