1use std::fmt::Debug;
2use std::fmt::Display;
3use std::hash::Hash;
4
5use iri_s::IriS;
6use oxrdf::BlankNode as OxBlankNode;
7use oxrdf::Literal as OxLiteral;
8use oxrdf::NamedNode as OxNamedNode;
9use oxrdf::Subject as OxSubject;
10use oxrdf::SubjectRef;
11use oxrdf::Term as OxTerm;
12use oxrdf::Triple as OxTriple;
13use prefixmap::PrefixMap;
14use prefixmap::PrefixMapError;
15use rust_decimal::Decimal;
16
17use crate::lang::Lang;
18use crate::literal::Literal as SRDFLiteral;
19use crate::matcher::Matcher;
20use crate::Object;
21
22pub trait Rdf: Sized {
23 type Subject: Subject
24 + From<Self::IRI>
25 + From<Self::BNode>
26 + From<IriS>
27 + TryFrom<Self::Term>
28 + TryFrom<Object>
29 + Matcher<Self::Subject>;
30
31 type IRI: Iri + From<IriS> + TryFrom<Self::Term> + Matcher<Self::IRI>;
32
33 type Term: Term
34 + From<Self::Subject>
35 + From<Self::IRI>
36 + From<Self::BNode>
37 + From<Self::Literal>
38 + From<IriS>
39 + From<Object>
40 + Into<Object>
41 + Matcher<Self::Term>;
42
43 type BNode: BlankNode + TryFrom<Self::Term>;
44
45 type Literal: Literal
46 + From<bool>
47 + From<String>
48 + From<i128>
49 + From<f64>
50 + TryFrom<Self::Term>
51 + From<SRDFLiteral>;
52
53 type Triple: Triple<Self::Subject, Self::IRI, Self::Term>;
54
55 type Err: Display;
56
57 fn qualify_iri(&self, iri: &Self::IRI) -> String;
58 fn qualify_subject(&self, subj: &Self::Subject) -> String;
59 fn qualify_term(&self, term: &Self::Term) -> String;
60
61 fn prefixmap(&self) -> Option<PrefixMap>;
62
63 fn resolve_prefix_local(&self, prefix: &str, local: &str) -> Result<IriS, PrefixMapError>;
65}
66
67#[derive(PartialEq)]
68pub enum TermKind {
69 Iri,
70 BlankNode,
71 Literal,
72 Triple,
73}
74
75pub trait Subject: Debug + Display + PartialEq + Clone + Eq + Hash {
76 fn kind(&self) -> TermKind;
77
78 fn is_iri(&self) -> bool {
79 self.kind() == TermKind::Iri
80 }
81
82 fn is_blank_node(&self) -> bool {
83 self.kind() == TermKind::BlankNode
84 }
85
86 fn is_triple(&self) -> bool {
87 self.kind() == TermKind::Triple
88 }
89}
90
91impl Subject for OxSubject {
92 fn kind(&self) -> TermKind {
93 match self {
94 OxSubject::NamedNode(_) => TermKind::Iri,
95 OxSubject::BlankNode(_) => TermKind::BlankNode,
96 #[cfg(feature = "rdf-star")]
97 OxSubject::Triple(_) => TermKind::Triple,
98 }
99 }
100}
101
102impl Subject for SubjectRef<'_> {
103 fn kind(&self) -> TermKind {
104 match self {
105 SubjectRef::NamedNode(_) => TermKind::Iri,
106 SubjectRef::BlankNode(_) => TermKind::BlankNode,
107 #[cfg(feature = "rdf-star")]
108 SubjectRef::Triple(_) => TermKind::Triple,
109 }
110 }
111}
112
113impl Matcher<OxSubject> for OxSubject {
114 fn value(&self) -> Option<OxSubject> {
115 Some(self.clone())
116 }
117}
118
119pub trait Iri: Debug + Display + Hash + Eq + Ord + Clone {
120 fn as_str(&self) -> &str;
121}
122
123impl Iri for OxNamedNode {
124 fn as_str(&self) -> &str {
125 self.as_str()
126 }
127}
128
129impl Matcher<OxNamedNode> for OxNamedNode {
130 fn value(&self) -> Option<OxNamedNode> {
131 Some(self.clone())
132 }
133}
134
135pub trait Term: Debug + Clone + Display + PartialEq + Eq + Hash {
136 fn kind(&self) -> TermKind;
137
138 fn is_iri(&self) -> bool {
139 self.kind() == TermKind::Iri
140 }
141
142 fn is_blank_node(&self) -> bool {
143 self.kind() == TermKind::BlankNode
144 }
145
146 fn is_literal(&self) -> bool {
147 self.kind() == TermKind::Literal
148 }
149
150 fn is_triple(&self) -> bool {
151 self.kind() == TermKind::Triple
152 }
153}
154
155impl Term for OxTerm {
156 fn kind(&self) -> TermKind {
157 match self {
158 OxTerm::NamedNode(_) => TermKind::Iri,
159 OxTerm::BlankNode(_) => TermKind::BlankNode,
160 OxTerm::Literal(_) => TermKind::Literal,
161 #[cfg(feature = "rdf-star")]
162 OxTerm::Triple(_) => TermKind::Triple,
163 }
164 }
165}
166
167impl Matcher<OxTerm> for OxTerm {
168 fn value(&self) -> Option<OxTerm> {
169 Some(self.clone())
170 }
171}
172
173pub trait Literal: Debug + Clone + Display + PartialEq + Eq + Hash {
174 fn lexical_form(&self) -> &str;
175
176 fn lang(&self) -> Option<&str>;
177
178 fn datatype(&self) -> &str;
179
180 fn as_bool(&self) -> Option<bool> {
181 match self.lexical_form() {
182 "true" => Some(true),
183 "false" => Some(false),
184 _ => None,
185 }
186 }
187
188 fn as_integer(&self) -> Option<isize> {
189 self.lexical_form().parse().ok()
190 }
191
192 fn as_double(&self) -> Option<f64> {
193 self.lexical_form().parse().ok()
194 }
195
196 fn as_decimal(&self) -> Option<Decimal> {
197 self.lexical_form().parse().ok()
198 }
199
200 fn as_literal(&self) -> SRDFLiteral {
201 if let Some(bool) = self.as_bool() {
202 SRDFLiteral::boolean(bool)
203 } else if let Some(int) = self.as_integer() {
204 SRDFLiteral::integer(int)
205 } else if let Some(decimal) = self.as_double() {
206 SRDFLiteral::double(decimal)
207 } else if let Some(decimal) = self.as_decimal() {
208 SRDFLiteral::decimal(decimal)
209 } else if let Some(lang) = self.lang() {
210 SRDFLiteral::lang_str(self.lexical_form(), Lang::new_unchecked(lang))
211 } else {
212 SRDFLiteral::str(self.lexical_form())
213 }
214 }
215}
216
217impl Literal for OxLiteral {
218 fn lexical_form(&self) -> &str {
219 self.value()
220 }
221
222 fn lang(&self) -> Option<&str> {
223 self.language()
224 }
225
226 fn datatype(&self) -> &str {
227 self.datatype().as_str()
228 }
229}
230
231pub trait BlankNode: Debug + Display + PartialEq {
232 fn new(id: impl Into<String>) -> Self;
233 fn id(&self) -> &str;
234}
235
236impl BlankNode for OxBlankNode {
237 fn new(id: impl Into<String>) -> Self {
238 OxBlankNode::new_unchecked(id)
239 }
240
241 fn id(&self) -> &str {
242 self.as_str()
243 }
244}
245
246pub trait Triple<S, P, O>: Debug + Clone + Display
247where
248 S: Subject,
249 P: Iri,
250 O: Term,
251{
252 fn new(subj: impl Into<S>, pred: impl Into<P>, obj: impl Into<O>) -> Self;
253
254 fn subj(&self) -> S;
255 fn pred(&self) -> P;
256 fn obj(&self) -> O;
257
258 fn into_components(self) -> (S, P, O);
259
260 fn into_subject(self) -> S {
261 self.into_components().0
262 }
263
264 fn into_predicate(self) -> P {
265 self.into_components().1
266 }
267
268 fn into_object(self) -> O {
269 self.into_components().2
270 }
271}
272
273impl Triple<OxSubject, OxNamedNode, OxTerm> for OxTriple {
274 fn new(
275 subj: impl Into<OxSubject>,
276 pred: impl Into<OxNamedNode>,
277 obj: impl Into<OxTerm>,
278 ) -> Self {
279 OxTriple::new(subj, pred, obj)
280 }
281
282 fn subj(&self) -> OxSubject {
283 self.subject.clone()
284 }
285
286 fn pred(&self) -> OxNamedNode {
287 self.predicate.clone()
288 }
289
290 fn obj(&self) -> OxTerm {
291 self.object.clone()
292 }
293
294 fn into_components(self) -> (OxSubject, OxNamedNode, OxTerm) {
295 (self.subject, self.predicate, self.object)
296 }
297}