1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
#![allow(clippy::module_name_repetitions)]
//! Module for handling checksums.
use serde::{Deserialize, Serialize};
use std::fmt;
mod digest;
pub use self::digest::{MD5, SHA256};
/// The types of checksums supported by Hoard.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChecksumType {
/// MD5 checksum -- provided for backwards compatibility with older versions of Hoard.
MD5,
/// SHA256 checksum -- currently the default.
SHA256,
}
impl Default for ChecksumType {
fn default() -> Self {
Self::SHA256
}
}
/// A file's checksum as a human-readable string.
///
/// If you have a choice of which variant to construct,
/// prefer using [`HoardItem::system_checksum`](crate::hoard_item::HoardItem::system_checksum)
/// or [`HoardItem::hoard_checksum`](crate::hoard_item::HoardItem::system_checksum) with the
/// return value of [`ChecksumType::default()`]
///
/// # TODO
///
/// - Ensure that the contained values can never be invalid for the associated checksum type.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Checksum {
/// An MD5 checksum -- provided for backwards compatibility with older versions of Hoard.
MD5(MD5),
/// A SHA256 checksum -- currently the default.
SHA256(SHA256),
}
impl Checksum {
/// Returns the [`ChecksumType`] for this `Checksum`.
///
/// ```
/// # use hoard::checksum::{Checksum, ChecksumType};
/// let checksum = Checksum::SHA256("50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c".parse().unwrap());
/// assert_eq!(checksum.typ(), ChecksumType::SHA256);
/// let checksum = Checksum::MD5("ae2b1fca515949e5d54fb22b8ed95575".parse().unwrap());
/// assert_eq!(checksum.typ(), ChecksumType::MD5);
/// ```
#[must_use]
pub fn typ(&self) -> ChecksumType {
match self {
Self::MD5(_) => ChecksumType::MD5,
Self::SHA256(_) => ChecksumType::SHA256,
}
}
}
impl fmt::Display for Checksum {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MD5(md5) => write!(f, "md5({md5})"),
Self::SHA256(sha256) => write!(f, "sha256({sha256})"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_checksum_display() {
let shasum = "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c";
let checksum = Checksum::SHA256(shasum.parse().unwrap());
assert_eq!(format!("sha256({shasum})"), checksum.to_string());
let md5sum = "ae2b1fca515949e5d54fb22b8ed95575";
let checksum = Checksum::MD5(md5sum.parse().unwrap());
assert_eq!(format!("md5({md5sum})"), checksum.to_string());
}
#[test]
fn test_checksum_type() {
assert_eq!(
ChecksumType::MD5,
Checksum::MD5("ae2b1fca515949e5d54fb22b8ed95575".parse().unwrap()).typ()
);
assert_eq!(
ChecksumType::SHA256,
Checksum::SHA256(
"50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c"
.parse()
.unwrap()
)
.typ()
);
}
}