atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
1a144ee92b627d87d2ff575eded19a9b8baa3fe1
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/link.rsRust94 lines2.4 KB
1
use std::fmt;
2
3
pub const REL_BASE: &str = "https://jelq.dev/rels/";
4
5
enum Rel<'a> {
6
    Jelq(&'a str),
7
    Registered(&'a str),
8
}
9
10
/// One RFC 8288 link. `allow`, `lubricant` and `intensity` are extension attributes (§3), so a client never
11
/// has to guess what a target accepts.
12
pub struct Link<'a> {
13
    href: &'a str,
14
    rel: Rel<'a>,
15
    title: Option<&'a str>,
16
    allow: Option<&'a str>,
17
    lubricant: Option<&'a str>,
18
    intensity: Option<&'a str>,
19
}
20
21
impl<'a> Link<'a> {
22
    fn new(href: &'a str, rel: Rel<'a>) -> Self {
23
        Self {
24
            href,
25
            rel,
26
            title: None,
27
            allow: None,
28
            lubricant: None,
29
            intensity: None,
30
        }
31
    }
32
33
    /// A relation of this game's own, named under `REL_BASE`.
34
    pub fn jelq(href: &'a str, rel: &'a str) -> Self {
35
        Self::new(href, Rel::Jelq(rel))
36
    }
37
38
    /// A relation from the IANA registry, such as `next` or `alternate`.
39
    pub fn registered(href: &'a str, rel: &'a str) -> Self {
40
        Self::new(href, Rel::Registered(rel))
41
    }
42
43
    pub fn title(self, title: &'a str) -> Self {
44
        Self {
45
            title: Some(title),
46
            ..self
47
        }
48
    }
49
50
    pub fn allow(self, allow: &'a str) -> Self {
51
        Self {
52
            allow: Some(allow),
53
            ..self
54
        }
55
    }
56
57
    pub fn lubricant(self, lubricant: Option<&'a str>) -> Self {
58
        Self { lubricant, ..self }
59
    }
60
61
    pub fn intensity(self, intensity: Option<&'a str>) -> Self {
62
        Self { intensity, ..self }
63
    }
64
}
65
66
impl fmt::Display for Link<'_> {
67
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68
        write!(f, "<{}>; rel=\"", self.href)?;
69
        match self.rel {
70
            Rel::Jelq(rel) => write!(f, "{REL_BASE}{rel}\"")?,
71
            Rel::Registered(rel) => write!(f, "{rel}\"")?,
72
        }
73
        for (name, value) in [
74
            ("title", self.title),
75
            ("allow", self.allow),
76
            ("lubricant", self.lubricant),
77
            ("intensity", self.intensity),
78
        ] {
79
            if let Some(value) = value {
80
                write!(f, "; {name}=\"{value}\"")?;
81
            }
82
        }
83
        Ok(())
84
    }
85
}
86
87
/// A `Link` header value listing every link in order.
88
pub fn join<'a>(links: impl IntoIterator<Item = Link<'a>>) -> String {
89
    links
90
        .into_iter()
91
        .map(|link| link.to_string())
92
        .collect::<Vec<_>>()
93
        .join(", ")
94
}