1use super::resolve::{BaseIri, BaseIriRef};
4use super::{is_absolute_iri_ref, is_valid_iri_ref, wrap, InvalidIri, IsIri, IsIriRef, Result};
5use std::borrow::Borrow;
6use std::fmt::Display;
7
8wrap! { Iri borrowing str :
9 pub fn new(iri: T) -> Result<Self, InvalidIri> {
13 if is_absolute_iri_ref(iri.borrow()) {
14 Ok(Iri(iri))
15 } else {
16 Err(InvalidIri(iri.borrow().to_string()))
17 }
18 }
19
20 pub fn resolve<U: IsIriRef>(&self, rel: U) -> Iri<String> {
26 self.as_base().resolve(rel)
27 }
28
29 pub fn as_base(&self) -> BaseIri<&str> {
32 BaseIri::new(self.0.borrow()).unwrap()
33 }
34
35 pub fn to_base(self) -> BaseIri<T>
38 where
39 T: std::ops::Deref<Target = str>,
40 {
41 BaseIri::new(self.0).unwrap()
42 }
43}
44
45impl<T: Borrow<str>> IsIriRef for Iri<T> {}
46impl<T: Borrow<str>> IsIri for Iri<T> {}
47
48impl<T: Borrow<str>> Display for Iri<T> {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 write!(f, "{}", self.0.borrow())
51 }
52}
53
54wrap! { IriRef borrowing str :
57 pub fn new(iri: T) -> Result<Self, InvalidIri> {
61 if is_valid_iri_ref(iri.borrow()) {
62 Ok(IriRef(iri))
63 } else {
64 Err(InvalidIri(iri.borrow().to_string()))
65 }
66 }
67
68 pub fn resolve<U: IsIriRef>(&self, rel: U) -> IriRef<String> {
74 self.as_base().resolve(rel)
75 }
76
77 pub fn as_base(&self) -> BaseIriRef<&str> {
80 BaseIriRef::new(self.0.borrow()).unwrap()
81 }
82
83 pub fn to_base(self) -> BaseIriRef<T>
86 where
87 T: std::ops::Deref<Target = str>,
88 {
89 BaseIriRef::new(self.0).unwrap()
90 }
91}
92
93impl<T: Borrow<str>> IsIriRef for IriRef<T> {}
94
95impl<T: Borrow<str>> Display for IriRef<T> {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 write!(f, "{}", self.0.borrow())
98 }
99}
100
101#[cfg(test)]
104mod test {
105 use super::*;
106 use crate::test::*;
107
108 #[test]
109 fn iri() {
110 for (txt, (abs, ..)) in POSITIVE_IRIS {
111 assert!(Iri::new(*txt).is_ok() == *abs);
112 }
113 for txt in NEGATIVE_IRIS {
114 assert!(Iri::new(*txt).is_err());
115 }
116 }
117
118 #[test]
119 fn iri_box() {
120 for (txt, (abs, ..)) in POSITIVE_IRIS {
121 assert!(Iri::new(Box::from(txt as &str)).is_ok() == *abs);
122 }
123 for txt in NEGATIVE_IRIS {
124 assert!(Iri::new(Box::from(txt as &str)).is_err());
125 }
126 }
127
128 #[test]
129 fn iri_ref() {
130 for (txt, _) in POSITIVE_IRIS {
131 assert!(IriRef::new(*txt).is_ok());
132 }
133 for txt in NEGATIVE_IRIS {
134 assert!(IriRef::new(*txt).is_err());
135 }
136 for (txt, _) in RELATIVE_IRIS {
137 assert!(IriRef::new(*txt).is_ok());
138 }
139 }
140
141 #[test]
142 fn iri_ref_box() {
143 for (txt, _) in POSITIVE_IRIS {
144 assert!(IriRef::new(Box::from(txt as &str)).is_ok());
145 }
146 for txt in NEGATIVE_IRIS {
147 assert!(IriRef::new(Box::from(txt as &str)).is_err());
148 }
149 for (txt, _) in RELATIVE_IRIS {
150 assert!(IriRef::new(Box::from(txt as &str)).is_ok());
151 }
152 }
153
154 #[test]
155 fn heterogeneous_comparison() {
156 let iri1 = Iri::new(String::from("http://example.com/")).unwrap();
157 let iri2 = Iri::new_unchecked(iri1.as_str());
158 assert_eq!(iri1, iri2);
159 }
160}