aster_forge_utils/
avatar.rs1use md5::{Digest, Md5};
9
10#[must_use]
12pub fn gravatar_hash(email: &str) -> String {
13 let normalized = email.trim().to_lowercase();
14 let mut hasher = Md5::new();
15 hasher.update(normalized.as_bytes());
16 hex_lower(&hasher.finalize())
17}
18
19#[must_use]
21pub fn gravatar_url(email: &str, size: u32, base_url: &str) -> String {
22 let hash = gravatar_hash(email);
23 let base = base_url.trim_end_matches('/');
24 format!("{base}/{hash}?d=identicon&s={size}&r=g")
25}
26
27fn hex_lower(bytes: &[u8]) -> String {
28 const HEX: &[u8; 16] = b"0123456789abcdef";
29 let mut output = String::with_capacity(bytes.len() * 2);
30 for byte in bytes {
31 output.push(char::from(HEX[usize::from(byte >> 4)]));
32 output.push(char::from(HEX[usize::from(byte & 0x0f)]));
33 }
34 output
35}
36
37#[cfg(test)]
38mod tests {
39 use super::{gravatar_hash, gravatar_url};
40
41 #[test]
42 fn gravatar_hash_trims_and_lowercases_email() {
43 assert_eq!(
44 gravatar_hash(" MyEmailAddress@example.com "),
45 "0bc83cb571cd1c50ba6f3e8a78ef1346"
46 );
47 }
48
49 #[test]
50 fn gravatar_url_uses_default_query_parameters_and_trims_base_slashes() {
51 assert_eq!(
52 gravatar_url("user@example.com", 512, "https://www.gravatar.com/avatar"),
53 "https://www.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af?d=identicon&s=512&r=g"
54 );
55 assert_eq!(
56 gravatar_url("user@example.com", 1024, "https://mirror.example/avatar/"),
57 "https://mirror.example/avatar/b58996c504c5638798eb6b511e6f49af?d=identicon&s=1024&r=g"
58 );
59 }
60}