/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use base64::{Engine, prelude::BASE64_URL_SAFE}; use sha2::Sha256; use std::{ fmt::Display, hash::{Hash, Hasher}, }; pub struct HashKey(pub T); impl Display for HashKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use sha2::Digest; struct ShaHasher(Sha256); impl Hasher for ShaHasher { fn finish(&self) -> u64 { unreachable!() } fn write(&mut self, bytes: &[u8]) { self.0.update(bytes); } } let mut d = ShaHasher(sha2::Sha256::new()); self.0.hash(&mut d); let d = d.0.finalize(); f.write_str(&BASE64_URL_SAFE.encode(d)) } } const SAFE_CHARS: percent_encoding::AsciiSet = percent_encoding::CONTROLS .add(b'.') .add(b'%') .add(b'/') .add(b'#') .add(b'?') .add(b'@'); pub struct EscapeKey(pub T); impl Display for EscapeKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // TODO perf f.write_str( &percent_encoding::utf8_percent_encode(&self.0.to_string(), &SAFE_CHARS) .to_string() .replace("%", "@"), ) } }