1use std::cmp::Ordering;
2use std::fmt;
3
4use crate::algorithm::Algorithm;
5use crate::errors::Error;
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
14pub struct Hash {
15 pub algorithm: Algorithm,
16 pub digest: String,
17}
18
19impl PartialOrd for Hash {
20 fn partial_cmp(&self, other: &Hash) -> Option<Ordering> {
21 Some(self.cmp(other))
22 }
23}
24
25impl Ord for Hash {
26 fn cmp(&self, other: &Hash) -> Ordering {
27 self.algorithm.cmp(&other.algorithm)
28 }
29}
30impl fmt::Display for Hash {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 write!(f, "{}-{}", self.algorithm, self.digest)
33 }
34}
35
36impl std::str::FromStr for Hash {
37 type Err = Error;
38
39 fn from_str(s: &str) -> Result<Hash, Self::Err> {
43 let mut parsed = s.trim().split(|c| c == '-');
44 let algorithm = parsed
45 .next()
46 .ok_or_else(|| Error::ParseIntegrityError(s.into()))?
47 .parse()?;
48 let digest = String::from(
49 parsed
50 .next()
51 .ok_or_else(|| Error::ParseIntegrityError(s.into()))?,
52 );
53 Ok(Hash { algorithm, digest })
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::Algorithm;
60 use super::Hash;
61
62 #[test]
63 fn hash_stringify() {
64 assert_eq!(
65 format!(
66 "{}",
67 Hash {
68 algorithm: Algorithm::Sha256,
69 digest: String::from("deadbeef==")
70 }
71 ),
72 "sha256-deadbeef=="
73 )
74 }
75
76 #[test]
77 fn parsing() {
78 assert_eq!(
79 " sha256-deadbeef== \n".parse::<Hash>().unwrap(),
80 Hash {
81 algorithm: Algorithm::Sha256,
82 digest: String::from("deadbeef==")
83 }
84 )
85 }
86
87 #[test]
88 #[should_panic]
89 fn bad_algorithm() {
90 "sha7-deadbeef==".parse::<Hash>().unwrap();
92 }
93
94 #[test]
95 fn ordering() {
96 let mut arr = [
97 Hash {
98 algorithm: Algorithm::Sha1,
99 digest: String::from("foo=="),
100 },
101 Hash {
102 algorithm: Algorithm::Sha256,
103 digest: String::from("foo=="),
104 },
105 Hash {
106 algorithm: Algorithm::Sha384,
107 digest: String::from("foo=="),
108 },
109 Hash {
110 algorithm: Algorithm::Sha512,
111 digest: String::from("foo=="),
112 },
113 Hash {
114 algorithm: Algorithm::Xxh3,
115 digest: String::from("foo=="),
116 },
117 ];
118 arr.sort_unstable();
119 assert_eq!(
120 arr,
121 [
122 Hash {
123 algorithm: Algorithm::Sha512,
124 digest: String::from("foo==")
125 },
126 Hash {
127 algorithm: Algorithm::Sha384,
128 digest: String::from("foo==")
129 },
130 Hash {
131 algorithm: Algorithm::Sha256,
132 digest: String::from("foo==")
133 },
134 Hash {
135 algorithm: Algorithm::Sha1,
136 digest: String::from("foo==")
137 },
138 Hash {
139 algorithm: Algorithm::Xxh3,
140 digest: String::from("foo==")
141 }
142 ]
143 )
144 }
145}