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