use magnetar_core::web_model::{content_type::ContentXrdXml, rel::RelLrdd, Rel}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum XrdXml { #[serde(rename = "XRD")] Xrd(Xrd), } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Xrd { #[serde(rename = "@xmlns")] xmlns: String, #[serde(rename = "Link")] links: Vec, } impl Xrd { pub fn default_host_meta(protocol: &str, domain: &str) -> Xrd { Xrd { xmlns: r#"http://docs.oasis-open.org/ns/xri/xrd-1.0"#.to_string(), links: vec![Link { rel: Some(RelLrdd.rel().to_string()), r#type: Some(ContentXrdXml.as_ref().to_string()), href: None, template: Some(format!( "{}://{}/.well-known/webfinger?resource={{uri}}", protocol, domain )), }], } } pub fn get_webfinger_template(&self) -> Option<&str> { self.links .iter() .find(|l| { l.r#type.as_deref() == Some(ContentXrdXml.as_ref()) && l.rel.as_deref() == Some(RelLrdd.as_ref()) }) .and_then(|l| l.template.as_deref()) } } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename = "Link")] pub struct Link { #[serde(rename = "@rel")] #[serde(skip_serializing_if = "Option::is_none")] rel: Option, #[serde(rename = "@type")] #[serde(skip_serializing_if = "Option::is_none")] r#type: Option, #[serde(rename = "@href")] #[serde(skip_serializing_if = "Option::is_none")] href: Option, #[serde(rename = "@template")] #[serde(skip_serializing_if = "Option::is_none")] template: Option, } #[cfg(test)] mod test { use std::error::Error; use crate::{Xrd, XrdXml}; #[test] fn should_parse_host_meta() -> Result<(), Box> { let xml = r#" "#; let XrdXml::Xrd(xrd) = quick_xml::de::from_str::(xml)?; assert_eq!(xrd, Xrd::default_host_meta("https", "example.org")); Ok(()) } #[test] fn should_fail_on_invalid_root_tag() { let xml = r#" "#; let xrd = quick_xml::de::from_str::(xml); assert!(xrd.is_err()); } }