ekg_namespace/
namespace.rs1use std::{
2 fmt::{Display, Formatter},
3 hash::{Hash, Hasher},
4};
5
6#[derive(Debug, Clone)]
15pub struct Namespace {
16 pub name: String,
18 pub iri: fluent_uri::Uri<String>,
20}
21
22impl Eq for Namespace {}
23
24impl PartialEq for Namespace {
25 fn eq(&self, other: &Self) -> bool {
26 self.name == other.name && self.iri.as_str() == other.iri.as_str()
27 }
28}
29
30impl Hash for Namespace {
31 fn hash<H: Hasher>(&self, state: &mut H) { self.name.hash(state); }
32}
33
34impl Display for Namespace {
35 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{} <{}>", self.name.as_str(), self.iri)
38 }
39}
40
41impl Namespace {
42 pub fn declare(name: &str, iri: &fluent_uri::Uri<&str>) -> Result<Self, ekg_error::Error> {
43 match iri.to_string().chars().last() {
44 Some('/') | Some('#') => Ok(Self { name: name.to_string(), iri: iri.to_owned() }),
45 _ => {
46 tracing::error!("{} does not end with either / or #", iri);
47 Err(ekg_error::Error::IncorrectBaseIRI { iri: iri.to_string() })
48 },
49 }
50 }
51
52 pub fn declare_iref_iri(name: &str, iri: &iref::Iri) -> Result<Self, ekg_error::Error> {
56 match iri.to_string().chars().last() {
57 Some('/') | Some('#') => {
58 Ok(Self {
59 name: name.to_string(),
60 iri: fluent_uri::Uri::parse(iri.as_str())?.to_owned(),
61 })
62 },
63 _ => {
64 tracing::error!("{} does not end with either / or #", iri);
65 Err(ekg_error::Error::IncorrectBaseIRI { iri: iri.to_string() })
66 },
67 }
68 }
69
70 pub fn declare_from_str(name: &str, iri: &str) -> Result<Self, ekg_error::Error> {
71 Self::declare(name, &fluent_uri::Uri::parse(iri)?)
72 }
73
74 pub fn with_local_name(&self, name: &str) -> Result<fluent_uri::Uri<String>, ekg_error::Error> {
78 let iri_str = match self.iri.to_string().chars().last().unwrap() {
79 '/' | '#' => format!("{}{name}", self.iri),
80 _ => {
81 panic!("{} does not end with either / or #", self.iri)
82 },
83 };
84
85 Ok(fluent_uri::Uri::parse_from(iri_str).map_err(|(_s, e)| e)?)
86 }
87
88 #[cfg(all(feature = "rdftk-support", not(target_arch = "wasm32")))]
89 pub fn as_rdftk_iri_ref(&self) -> Result<rdftk_iri::IRIRef, rdftk_iri::error::Error> {
90 Ok(rdftk_iri::IRIRef::new(self.as_rdftk_iri()?))
91 }
92
93 #[cfg(all(feature = "rdftk-support", not(target_arch = "wasm32")))]
94 pub fn as_rdftk_iri(&self) -> Result<rdftk_iri::IRI, rdftk_iri::error::Error> {
95 use std::str::FromStr;
96 rdftk_iri::IRI::from_str(self.iri.as_str())
97 }
98
99 pub fn as_sparql_prefix(&self) -> String { format!("PREFIX {} <{}>", self.name, self.iri) }
101
102 pub fn as_turtle_prefix(&self) -> String { format!("@prefix {} <{}> .", self.name, self.iri) }
104}
105
106#[cfg(test)]
107mod tests {
108 #[test_log::test]
109 fn test_a_prefix() -> Result<(), ekg_error::Error> {
110 let namespace = crate::Namespace::declare(
111 "test:",
112 &fluent_uri::Uri::parse("http://whatever.kom/test#").unwrap(),
113 )
114 .unwrap();
115 let x = namespace.with_local_name("abc")?;
116
117 assert_eq!(
118 x.to_string().as_str(),
119 "http://whatever.kom/test#abc"
120 );
121 Ok(())
122 }
123
124 #[test_log::test]
125 fn test_b_prefix() -> Result<(), ekg_error::Error> {
126 let namespace = crate::Namespace::declare(
127 "test:",
128 &fluent_uri::Uri::parse("http://whatever.kom/test/").unwrap(),
129 )
130 .unwrap();
131 let x = namespace.with_local_name("abc")?;
132
133 assert_eq!(
134 x.to_string().as_str(),
135 "http://whatever.kom/test/abc"
136 );
137 Ok(())
138 }
139}