Skip to main content

link_relation/
lib.rs

1//! # Link Relations
2//!
3//! Registered relation types for
4//! [Web Linking (RFC8288)](https://datatracker.ietf.org/doc/html/rfc8288).
5//!
6//! Definitions generated from IANA's
7//! [link relations registry](https://www.iana.org/assignments/link-relations/link-relations.xml).
8//!
9//! Please check [LinkRelation] for all registered link relation types.
10//!
11//! ```rust
12//! use link_relation::LinkRelation;
13//! assert_eq!(LinkRelation::ACL.get_name(), "acl");
14//! ```
15//!
16//! ## Crate Features
17//!
18//! - **serde** - Serialization and deserialization support with
19//!   [serde](https://crates.io/crates/serde).
20
21mod generated;
22pub use generated::{LinkRelation, LINK_RELATIONS};
23
24#[cfg(feature = "serde")]
25mod serde;
26
27use std::error::Error;
28use std::fmt;
29use std::str::FromStr;
30
31/// Detailed link relation data.
32#[derive(Clone, Debug)]
33pub struct LinkRelationDetails {
34    pub name: String,
35    pub description: String,
36    pub reference: String,
37    pub notes: Option<String>,
38}
39
40/// Error definitions for parsing link relation with [FromStr].
41#[derive(Copy, Clone, Debug)]
42pub enum LinkRelationParsingError {
43    /// Cannot find this link relation variant.
44    NotFound,
45}
46
47impl fmt::Display for LinkRelationParsingError {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(
50            f,
51            "Error while parsing LinkRelation: {}",
52            match self {
53                LinkRelationParsingError::NotFound => "Not found",
54            }
55        )
56    }
57}
58
59impl Error for LinkRelationParsingError {}
60
61impl LinkRelation {
62    /// Get the associated LinkRelation definition.
63    pub fn get_link_relation(&self) -> &LinkRelationDetails {
64        // It should never panic
65        LINK_RELATIONS.get(self).unwrap()
66    }
67
68    /// Get the original name of the specified link relation type.
69    pub fn get_name(&self) -> &str {
70        &self.get_link_relation().name
71    }
72
73    /// Get the description of the link relation.
74    pub fn get_description(&self) -> &str {
75        &self.get_link_relation().description
76    }
77
78    /// Get the reference of the link relation.
79    pub fn get_reference(&self) -> &str {
80        &self.get_link_relation().reference
81    }
82
83    /// Get the notes of the link relation.
84    pub fn get_notes(&self) -> Option<&str> {
85        let link_relation = self.get_link_relation();
86        link_relation.notes.as_deref()
87    }
88}
89
90impl FromStr for LinkRelation {
91    type Err = LinkRelationParsingError;
92
93    fn from_str(value: &str) -> Result<Self, Self::Err> {
94        let value_str = value.trim().to_lowercase();
95        LINK_RELATIONS
96            .iter()
97            .filter_map(|(k, v)| if value_str == v.name { Some(*k) } else { None })
98            .next()
99            .ok_or(LinkRelationParsingError::NotFound)
100    }
101}
102
103impl fmt::Display for LinkRelation {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        write!(f, "{}", self.get_name())
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::LinkRelation;
112
113    #[test]
114    fn test_to_string() {
115        assert_eq!(LinkRelation::ACL.to_string(), String::from("acl"));
116    }
117}