gitscope
← rgit / 0.1.4 / src/methods/filters.rs
https://dev.kronoz.win/r/rgit.git
src/methods/filters.rs · Rust
Blame Raw
  1// sorry clippy, we don't have a choice. askama forces this on us
  2#![allow(clippy::unnecessary_wraps, clippy::trivially_copy_pass_by_ref)]
  3
  4use std::{
  5    borrow::Borrow,
  6    sync::{Arc, LazyLock},
  7};
  8
  9use arc_swap::ArcSwap;
 10use rkyv::{
 11    rend::{i32_le, i64_le},
 12    tuple::ArchivedTuple2,
 13};
 14use time::{format_description::well_known::Rfc3339, OffsetDateTime, UtcOffset};
 15
 16// pub fn format_time(s: impl Borrow<time::OffsetDateTime>) -> Result<String, askama::Error> {
 17pub fn format_time(s: impl Into<Timestamp>) -> Result<String, askama::Error> {
 18    let s = s.into().0;
 19
 20    (*s.borrow())
 21        .format(&Rfc3339)
 22        .map_err(Box::from)
 23        .map_err(askama::Error::Custom)
 24}
 25
 26pub fn branch_query(branch: Option<&str>) -> String {
 27    if let Some(b) = branch {
 28        format!("?h={b}")
 29    } else {
 30        String::new()
 31    }
 32}
 33
 34pub fn timeago(s: impl Into<Timestamp>) -> Result<String, askama::Error> {
 35    Ok(timeago::Formatter::new()
 36        .convert((OffsetDateTime::now_utc() - s.into().0).try_into().unwrap()))
 37}
 38
 39pub fn file_perms(s: &u16) -> Result<String, askama::Error> {
 40    Ok(unix_mode::to_string(u32::from(*s)))
 41}
 42
 43pub fn hex(s: &[u8]) -> Result<String, askama::Error> {
 44    Ok(const_hex::encode(s))
 45}
 46
 47pub fn gravatar(email: &str) -> Result<&'static str, askama::Error> {
 48    static CACHE: LazyLock<ArcSwap<hashbrown::HashMap<&'static str, &'static str>>> =
 49        LazyLock::new(|| ArcSwap::new(Arc::new(hashbrown::HashMap::new())));
 50
 51    if let Some(res) = CACHE.load().get(email).copied() {
 52        return Ok(res);
 53    }
 54
 55    let url = format!(
 56        "https://www.gravatar.com/avatar/{}",
 57        const_hex::encode(md5::compute(email).0)
 58    );
 59    let key = Box::leak(Box::from(email));
 60    let url = url.leak();
 61
 62    CACHE.rcu(|curr| {
 63        let mut r = (**curr).clone();
 64        r.insert(key, url);
 65        r
 66    });
 67
 68    Ok(url)
 69}
 70
 71pub struct Timestamp(OffsetDateTime);
 72
 73impl From<&ArchivedTuple2<i64_le, i32_le>> for Timestamp {
 74    fn from(value: &ArchivedTuple2<i64_le, i32_le>) -> Self {
 75        Self(
 76            OffsetDateTime::from_unix_timestamp(value.0.to_native())
 77                .unwrap()
 78                .to_offset(UtcOffset::from_whole_seconds(value.1.to_native()).unwrap()),
 79        )
 80    }
 81}
 82
 83impl From<(i64, i32)> for Timestamp {
 84    fn from(value: (i64, i32)) -> Self {
 85        Self(
 86            OffsetDateTime::from_unix_timestamp(value.0)
 87                .unwrap()
 88                .to_offset(UtcOffset::from_whole_seconds(value.1).unwrap()),
 89        )
 90    }
 91}
 92
 93impl From<&(i64, i32)> for Timestamp {
 94    fn from(value: &(i64, i32)) -> Self {
 95        Self(
 96            OffsetDateTime::from_unix_timestamp(value.0)
 97                .unwrap()
 98                .to_offset(UtcOffset::from_whole_seconds(value.1).unwrap()),
 99        )
100    }
101}
102
103impl From<OffsetDateTime> for Timestamp {
104    fn from(value: OffsetDateTime) -> Self {
105        Self(value)
106    }
107}