rudof_rdf/rdf_impl/oxrdf_impl.rs
1use crate::rdf_core::{
2 Matcher,
3 term::{
4 BlankNode, Iri, Subject, Term, TermKind, Triple,
5 literal::{ConcreteLiteral, Lang, Literal},
6 },
7};
8use iri_s::IriS;
9use oxrdf::{
10 BlankNode as OxBlankNode, Literal as OxLiteral, NamedNode as OxNamedNode, NamedOrBlankNode as OxSubject,
11 NamedOrBlankNodeRef as OxSubjectRef, Term as OxTerm, Triple as OxTriple,
12};
13use prefixmap::IriRef;
14
15/// Implements the `Subject` trait for `OxSubject` (owned version).
16///
17/// This allows owned `NamedOrBlankNode` instances from `oxrdf` to be used
18/// as RDF subjects in the core trait system.
19impl Subject for OxSubject {
20 /// Returns the kind of term this subject represents.
21 ///
22 /// # Returns
23 /// - `TermKind::Iri` for named nodes (IRIs)
24 /// - `TermKind::BlankNode` for blank nodes
25 fn kind(&self) -> TermKind {
26 match self {
27 OxSubject::NamedNode(_) => TermKind::Iri,
28 OxSubject::BlankNode(_) => TermKind::BlankNode,
29 }
30 }
31}
32
33/// Implements the `Subject` trait for `OxSubjectRef` (borrowed version).
34///
35/// This allows borrowed `NamedOrBlankNodeRef` instances from `oxrdf` to be
36/// used as RDF subjects without requiring ownership.
37impl Subject for OxSubjectRef<'_> {
38 /// Returns the kind of term this subject reference represents.
39 ///
40 /// # Returns
41 /// - `TermKind::Iri` for named nodes (IRIs)
42 /// - `TermKind::BlankNode` for blank nodes
43 fn kind(&self) -> TermKind {
44 match self {
45 OxSubjectRef::NamedNode(_) => TermKind::Iri,
46 OxSubjectRef::BlankNode(_) => TermKind::BlankNode,
47 }
48 }
49}
50
51/// Implements the `Iri` trait for `OxNamedNode`.
52///
53/// Provides access to the string representation of an IRI from an `oxrdf`
54/// named node.
55impl Iri for OxNamedNode {
56 /// Returns the IRI as a string slice.
57 fn as_str(&self) -> &str {
58 self.as_str()
59 }
60}
61
62/// Implements the `Term` trait for `OxTerm`.
63///
64/// This is the main implementation for RDF terms, supporting IRIs, blank nodes,
65/// literals, and RDF-star quoted triples.
66impl Term for OxTerm {
67 /// Returns the kind of RDF term.
68 ///
69 /// # Returns
70 /// - `TermKind::Iri` for named nodes
71 /// - `TermKind::BlankNode` for blank nodes
72 /// - `TermKind::Literal` for literal values
73 /// - `TermKind::Triple` for RDF-star quoted triples
74 fn kind(&self) -> TermKind {
75 match self {
76 OxTerm::NamedNode(_) => TermKind::Iri,
77 OxTerm::BlankNode(_) => TermKind::BlankNode,
78 OxTerm::Literal(_) => TermKind::Literal,
79 OxTerm::Triple(_) => TermKind::Triple,
80 }
81 }
82
83 // Returns the lexical form of this term as an owned string.
84 /// # Returns
85 /// - For IRIs: the full IRI string
86 /// - For blank nodes: the blank node identifier (e.g., "_:b0")
87 /// - For literals: the literal value without datatype or language tag
88 /// - For triples: the string representation of the entire triple
89 fn lexical_form(&self) -> String {
90 match self {
91 OxTerm::NamedNode(iri) => iri.as_str().to_string(),
92 OxTerm::BlankNode(bnode) => bnode.as_str().to_string(),
93 OxTerm::Literal(literal) => literal.value().to_string(),
94 OxTerm::Triple(triple) => triple.to_string(),
95 }
96 }
97}
98
99/// Implements the `Matcher` trait for `OxNamedNode`, enabling pattern matching.
100///
101/// This trivial implementation always matches by cloning the named node.
102impl Matcher<OxNamedNode> for OxNamedNode {
103 /// Always returns `Some(self)` indicating a successful match.
104 fn value(&self) -> Option<&OxNamedNode> {
105 Some(self)
106 }
107}
108
109/// Implements the `Matcher` trait for `OxSubject`, enabling pattern matching.
110impl Matcher<OxSubject> for OxSubject {
111 /// Always returns `Some(self)` indicating a successful match.
112 fn value(&self) -> Option<&OxSubject> {
113 Some(self)
114 }
115}
116
117/// Implements the `Matcher` trait for `OxTerm`, enabling pattern matching.
118impl Matcher<OxTerm> for OxTerm {
119 /// Always returns `Some(self)` indicating a successful match.
120 fn value(&self) -> Option<&OxTerm> {
121 Some(self)
122 }
123}
124
125/// Implements the `Literal` trait for `OxLiteral`.
126///
127/// Provides access to literal values, language tags, and datatypes from
128/// `oxrdf` literals.
129impl Literal for OxLiteral {
130 /// Returns the lexical form of the literal as a string slice.
131 fn lexical_form(&self) -> &str {
132 self.value()
133 }
134
135 /// Returns the language tag if this is a language-tagged string.
136 ///
137 /// # Returns
138 /// - `Some(Lang)` if this literal has a language tag (e.g., "en", "es")
139 /// - `None` if this literal is not language-tagged
140 fn lang(&self) -> Option<Lang> {
141 self.language().and_then(|lang| Lang::new(lang).ok())
142 }
143
144 /// Returns the datatype IRI of this literal.
145 fn datatype(&self) -> IriRef {
146 IriRef::iri(IriS::new_unchecked(self.datatype().as_str()))
147 }
148
149 /// Attempts to convert this literal to a concrete typed value.
150 ///
151 /// # Returns
152 /// `Some(ConcreteLiteral)` if the literal can be parsed into a concrete type,
153 /// `None` otherwise.
154 fn to_concrete_literal(&self) -> Option<ConcreteLiteral> {
155 todo!()
156 }
157}
158
159/// Implements the `BlankNode` trait for `OxBlankNode`.
160///
161/// Provides construction and access to blank node identifiers.
162impl BlankNode for OxBlankNode {
163 /// Creates a new blank node with the given identifier.
164 ///
165 /// # Parameters
166 /// - `id`: The blank node identifier (converted to `String`)
167 fn new(id: impl Into<String>) -> Self {
168 OxBlankNode::new_unchecked(id)
169 }
170
171 /// Returns the identifier of this blank node.
172 fn id(&self) -> &str {
173 self.as_str()
174 }
175}
176
177/// Implements the `Triple` trait for `OxTriple`.
178///
179/// Provides construction, field access, and decomposition for RDF triples
180/// consisting of subject, predicate, and object.
181impl Triple<OxSubject, OxNamedNode, OxTerm> for OxTriple {
182 /// Creates a new RDF triple from subject, predicate, and object.
183 ///
184 /// # Parameters
185 /// - `subj`: The subject (IRI or blank node)
186 /// - `pred`: The predicate (IRI/named node)
187 /// - `obj`: The object (IRI, blank node, literal, or quoted triple)
188 fn new(subj: impl Into<OxSubject>, pred: impl Into<OxNamedNode>, obj: impl Into<OxTerm>) -> Self {
189 OxTriple::new(subj, pred, obj)
190 }
191
192 /// Returns a reference to the subject of this triple.
193 fn subj(&self) -> &OxSubject {
194 &self.subject
195 }
196
197 /// Returns a reference to the predicate of this triple.
198 fn pred(&self) -> &OxNamedNode {
199 &self.predicate
200 }
201
202 /// Returns a reference to the object of this triple.
203 fn obj(&self) -> &OxTerm {
204 &self.object
205 }
206
207 /// Consumes the triple and returns its components.
208 ///
209 /// This method is useful when you need owned values rather than references,
210 /// avoiding additional clones.
211 fn into_components(self) -> (OxSubject, OxNamedNode, OxTerm) {
212 (self.subject, self.predicate, self.object)
213 }
214}