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