oxrdf/
triple.rs

1use crate::blank_node::BlankNode;
2use crate::literal::Literal;
3use crate::named_node::NamedNode;
4use crate::{BlankNodeRef, LiteralRef, NamedNodeRef};
5use std::fmt;
6
7/// The owned union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
8#[derive(Eq, PartialEq, Debug, Clone, Hash)]
9pub enum NamedOrBlankNode {
10    NamedNode(NamedNode),
11    BlankNode(BlankNode),
12}
13
14impl NamedOrBlankNode {
15    #[inline]
16    pub fn is_named_node(&self) -> bool {
17        self.as_ref().is_named_node()
18    }
19
20    #[inline]
21    pub fn is_blank_node(&self) -> bool {
22        self.as_ref().is_blank_node()
23    }
24
25    #[inline]
26    pub fn as_ref(&self) -> NamedOrBlankNodeRef<'_> {
27        match self {
28            Self::NamedNode(node) => NamedOrBlankNodeRef::NamedNode(node.as_ref()),
29            Self::BlankNode(node) => NamedOrBlankNodeRef::BlankNode(node.as_ref()),
30        }
31    }
32}
33
34impl fmt::Display for NamedOrBlankNode {
35    #[inline]
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        self.as_ref().fmt(f)
38    }
39}
40
41impl From<NamedNode> for NamedOrBlankNode {
42    #[inline]
43    fn from(node: NamedNode) -> Self {
44        Self::NamedNode(node)
45    }
46}
47
48impl From<NamedNodeRef<'_>> for NamedOrBlankNode {
49    #[inline]
50    fn from(node: NamedNodeRef<'_>) -> Self {
51        node.into_owned().into()
52    }
53}
54
55impl From<BlankNode> for NamedOrBlankNode {
56    #[inline]
57    fn from(node: BlankNode) -> Self {
58        Self::BlankNode(node)
59    }
60}
61
62impl From<BlankNodeRef<'_>> for NamedOrBlankNode {
63    #[inline]
64    fn from(node: BlankNodeRef<'_>) -> Self {
65        node.into_owned().into()
66    }
67}
68
69/// The borrowed union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
70#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
71pub enum NamedOrBlankNodeRef<'a> {
72    NamedNode(NamedNodeRef<'a>),
73    BlankNode(BlankNodeRef<'a>),
74}
75
76impl NamedOrBlankNodeRef<'_> {
77    #[inline]
78    pub fn is_named_node(&self) -> bool {
79        match self {
80            Self::NamedNode(_) => true,
81            Self::BlankNode(_) => false,
82        }
83    }
84
85    #[inline]
86    pub fn is_blank_node(&self) -> bool {
87        match self {
88            Self::NamedNode(_) => false,
89            Self::BlankNode(_) => true,
90        }
91    }
92
93    #[inline]
94    pub fn into_owned(self) -> NamedOrBlankNode {
95        match self {
96            Self::NamedNode(node) => NamedOrBlankNode::NamedNode(node.into_owned()),
97            Self::BlankNode(node) => NamedOrBlankNode::BlankNode(node.into_owned()),
98        }
99    }
100}
101
102impl fmt::Display for NamedOrBlankNodeRef<'_> {
103    #[inline]
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            Self::NamedNode(node) => node.fmt(f),
107            Self::BlankNode(node) => node.fmt(f),
108        }
109    }
110}
111
112impl<'a> From<NamedNodeRef<'a>> for NamedOrBlankNodeRef<'a> {
113    #[inline]
114    fn from(node: NamedNodeRef<'a>) -> Self {
115        Self::NamedNode(node)
116    }
117}
118
119impl<'a> From<&'a NamedNode> for NamedOrBlankNodeRef<'a> {
120    #[inline]
121    fn from(node: &'a NamedNode) -> Self {
122        node.as_ref().into()
123    }
124}
125
126impl<'a> From<BlankNodeRef<'a>> for NamedOrBlankNodeRef<'a> {
127    #[inline]
128    fn from(node: BlankNodeRef<'a>) -> Self {
129        Self::BlankNode(node)
130    }
131}
132
133impl<'a> From<&'a BlankNode> for NamedOrBlankNodeRef<'a> {
134    #[inline]
135    fn from(node: &'a BlankNode) -> Self {
136        node.as_ref().into()
137    }
138}
139
140impl<'a> From<&'a NamedOrBlankNode> for NamedOrBlankNodeRef<'a> {
141    #[inline]
142    fn from(node: &'a NamedOrBlankNode) -> Self {
143        node.as_ref()
144    }
145}
146
147impl<'a> From<NamedOrBlankNodeRef<'a>> for NamedOrBlankNode {
148    #[inline]
149    fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
150        node.into_owned()
151    }
152}
153
154/// The owned union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node)  and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) (if the `rdf-star` feature is enabled).
155#[derive(Eq, PartialEq, Debug, Clone, Hash)]
156pub enum Subject {
157    NamedNode(NamedNode),
158    BlankNode(BlankNode),
159    #[cfg(feature = "rdf-star")]
160    Triple(Box<Triple>),
161}
162
163impl Subject {
164    #[inline]
165    pub fn is_named_node(&self) -> bool {
166        self.as_ref().is_named_node()
167    }
168
169    #[inline]
170    pub fn is_blank_node(&self) -> bool {
171        self.as_ref().is_blank_node()
172    }
173
174    #[cfg(feature = "rdf-star")]
175    #[inline]
176    pub fn is_triple(&self) -> bool {
177        self.as_ref().is_triple()
178    }
179
180    #[inline]
181    pub fn as_ref(&self) -> SubjectRef<'_> {
182        match self {
183            Self::NamedNode(node) => SubjectRef::NamedNode(node.as_ref()),
184            Self::BlankNode(node) => SubjectRef::BlankNode(node.as_ref()),
185            #[cfg(feature = "rdf-star")]
186            Self::Triple(triple) => SubjectRef::Triple(triple),
187        }
188    }
189}
190
191impl fmt::Display for Subject {
192    #[inline]
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        self.as_ref().fmt(f)
195    }
196}
197
198impl From<NamedNode> for Subject {
199    #[inline]
200    fn from(node: NamedNode) -> Self {
201        Self::NamedNode(node)
202    }
203}
204
205impl From<NamedNodeRef<'_>> for Subject {
206    #[inline]
207    fn from(node: NamedNodeRef<'_>) -> Self {
208        node.into_owned().into()
209    }
210}
211
212impl From<BlankNode> for Subject {
213    #[inline]
214    fn from(node: BlankNode) -> Self {
215        Self::BlankNode(node)
216    }
217}
218
219impl From<BlankNodeRef<'_>> for Subject {
220    #[inline]
221    fn from(node: BlankNodeRef<'_>) -> Self {
222        node.into_owned().into()
223    }
224}
225
226#[cfg(feature = "rdf-star")]
227impl From<Triple> for Subject {
228    #[inline]
229    fn from(node: Triple) -> Self {
230        Self::Triple(Box::new(node))
231    }
232}
233
234#[cfg(feature = "rdf-star")]
235impl From<Box<Triple>> for Subject {
236    #[inline]
237    fn from(node: Box<Triple>) -> Self {
238        Self::Triple(node)
239    }
240}
241
242#[cfg(feature = "rdf-star")]
243impl From<TripleRef<'_>> for Subject {
244    #[inline]
245    fn from(node: TripleRef<'_>) -> Self {
246        node.into_owned().into()
247    }
248}
249
250impl From<NamedOrBlankNode> for Subject {
251    #[inline]
252    fn from(node: NamedOrBlankNode) -> Self {
253        match node {
254            NamedOrBlankNode::NamedNode(node) => node.into(),
255            NamedOrBlankNode::BlankNode(node) => node.into(),
256        }
257    }
258}
259
260impl From<NamedOrBlankNodeRef<'_>> for Subject {
261    #[inline]
262    fn from(node: NamedOrBlankNodeRef<'_>) -> Self {
263        node.into_owned().into()
264    }
265}
266
267/// The borrowed union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) (if the `rdf-star` feature is enabled).
268#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
269pub enum SubjectRef<'a> {
270    NamedNode(NamedNodeRef<'a>),
271    BlankNode(BlankNodeRef<'a>),
272    #[cfg(feature = "rdf-star")]
273    Triple(&'a Triple),
274}
275
276impl SubjectRef<'_> {
277    #[inline]
278    pub fn is_named_node(&self) -> bool {
279        matches!(self, Self::NamedNode(_))
280    }
281
282    #[inline]
283    pub fn is_blank_node(&self) -> bool {
284        matches!(self, Self::BlankNode(_))
285    }
286
287    #[cfg(feature = "rdf-star")]
288    #[inline]
289    pub fn is_triple(&self) -> bool {
290        matches!(self, Self::Triple(_))
291    }
292
293    #[inline]
294    pub fn into_owned(self) -> Subject {
295        match self {
296            Self::NamedNode(node) => Subject::NamedNode(node.into_owned()),
297            Self::BlankNode(node) => Subject::BlankNode(node.into_owned()),
298            #[cfg(feature = "rdf-star")]
299            Self::Triple(triple) => Subject::Triple(Box::new(triple.clone())),
300        }
301    }
302}
303
304impl fmt::Display for SubjectRef<'_> {
305    #[inline]
306    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307        match self {
308            Self::NamedNode(node) => node.fmt(f),
309            Self::BlankNode(node) => node.fmt(f),
310            #[cfg(feature = "rdf-star")]
311            Self::Triple(triple) => write!(f, "<<{triple}>>"),
312        }
313    }
314}
315
316impl<'a> From<NamedNodeRef<'a>> for SubjectRef<'a> {
317    #[inline]
318    fn from(node: NamedNodeRef<'a>) -> Self {
319        Self::NamedNode(node)
320    }
321}
322
323impl<'a> From<&'a NamedNode> for SubjectRef<'a> {
324    #[inline]
325    fn from(node: &'a NamedNode) -> Self {
326        node.as_ref().into()
327    }
328}
329
330impl<'a> From<BlankNodeRef<'a>> for SubjectRef<'a> {
331    #[inline]
332    fn from(node: BlankNodeRef<'a>) -> Self {
333        Self::BlankNode(node)
334    }
335}
336
337impl<'a> From<&'a BlankNode> for SubjectRef<'a> {
338    #[inline]
339    fn from(node: &'a BlankNode) -> Self {
340        node.as_ref().into()
341    }
342}
343
344#[cfg(feature = "rdf-star")]
345impl<'a> From<&'a Triple> for SubjectRef<'a> {
346    #[inline]
347    fn from(node: &'a Triple) -> Self {
348        Self::Triple(node)
349    }
350}
351
352impl<'a> From<&'a Subject> for SubjectRef<'a> {
353    #[inline]
354    fn from(node: &'a Subject) -> Self {
355        node.as_ref()
356    }
357}
358
359impl<'a> From<SubjectRef<'a>> for Subject {
360    #[inline]
361    fn from(node: SubjectRef<'a>) -> Self {
362        node.into_owned()
363    }
364}
365
366impl<'a> From<NamedOrBlankNodeRef<'a>> for SubjectRef<'a> {
367    #[inline]
368    fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
369        match node {
370            NamedOrBlankNodeRef::NamedNode(node) => node.into(),
371            NamedOrBlankNodeRef::BlankNode(node) => node.into(),
372        }
373    }
374}
375
376impl<'a> From<&'a NamedOrBlankNode> for SubjectRef<'a> {
377    #[inline]
378    fn from(node: &'a NamedOrBlankNode) -> Self {
379        node.as_ref().into()
380    }
381}
382
383/// An owned RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term)
384///
385/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) (if the `rdf-star` feature is enabled).
386#[derive(Eq, PartialEq, Debug, Clone, Hash)]
387pub enum Term {
388    NamedNode(NamedNode),
389    BlankNode(BlankNode),
390    Literal(Literal),
391    #[cfg(feature = "rdf-star")]
392    Triple(Box<Triple>),
393}
394
395impl Term {
396    #[inline]
397    pub fn is_named_node(&self) -> bool {
398        self.as_ref().is_named_node()
399    }
400
401    #[inline]
402    pub fn is_blank_node(&self) -> bool {
403        self.as_ref().is_blank_node()
404    }
405
406    #[inline]
407    pub fn is_literal(&self) -> bool {
408        self.as_ref().is_literal()
409    }
410
411    #[cfg(feature = "rdf-star")]
412    #[inline]
413    pub fn is_triple(&self) -> bool {
414        self.as_ref().is_triple()
415    }
416
417    #[inline]
418    pub fn as_ref(&self) -> TermRef<'_> {
419        match self {
420            Self::NamedNode(node) => TermRef::NamedNode(node.as_ref()),
421            Self::BlankNode(node) => TermRef::BlankNode(node.as_ref()),
422            Self::Literal(literal) => TermRef::Literal(literal.as_ref()),
423            #[cfg(feature = "rdf-star")]
424            Self::Triple(triple) => TermRef::Triple(triple),
425        }
426    }
427}
428
429impl fmt::Display for Term {
430    #[inline]
431    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432        self.as_ref().fmt(f)
433    }
434}
435
436impl From<NamedNode> for Term {
437    #[inline]
438    fn from(node: NamedNode) -> Self {
439        Self::NamedNode(node)
440    }
441}
442
443impl From<NamedNodeRef<'_>> for Term {
444    #[inline]
445    fn from(node: NamedNodeRef<'_>) -> Self {
446        node.into_owned().into()
447    }
448}
449
450impl From<BlankNode> for Term {
451    #[inline]
452    fn from(node: BlankNode) -> Self {
453        Self::BlankNode(node)
454    }
455}
456
457impl From<BlankNodeRef<'_>> for Term {
458    #[inline]
459    fn from(node: BlankNodeRef<'_>) -> Self {
460        node.into_owned().into()
461    }
462}
463
464impl From<Literal> for Term {
465    #[inline]
466    fn from(literal: Literal) -> Self {
467        Self::Literal(literal)
468    }
469}
470
471impl From<LiteralRef<'_>> for Term {
472    #[inline]
473    fn from(literal: LiteralRef<'_>) -> Self {
474        literal.into_owned().into()
475    }
476}
477
478#[cfg(feature = "rdf-star")]
479impl From<Triple> for Term {
480    #[inline]
481    fn from(triple: Triple) -> Self {
482        Self::Triple(Box::new(triple))
483    }
484}
485
486#[cfg(feature = "rdf-star")]
487impl From<Box<Triple>> for Term {
488    #[inline]
489    fn from(node: Box<Triple>) -> Self {
490        Self::Triple(node)
491    }
492}
493
494#[cfg(feature = "rdf-star")]
495impl From<TripleRef<'_>> for Term {
496    #[inline]
497    fn from(triple: TripleRef<'_>) -> Self {
498        triple.into_owned().into()
499    }
500}
501
502impl From<NamedOrBlankNode> for Term {
503    #[inline]
504    fn from(node: NamedOrBlankNode) -> Self {
505        match node {
506            NamedOrBlankNode::NamedNode(node) => node.into(),
507            NamedOrBlankNode::BlankNode(node) => node.into(),
508        }
509    }
510}
511
512impl From<NamedOrBlankNodeRef<'_>> for Term {
513    #[inline]
514    fn from(node: NamedOrBlankNodeRef<'_>) -> Self {
515        node.into_owned().into()
516    }
517}
518
519impl From<Subject> for Term {
520    #[inline]
521    fn from(node: Subject) -> Self {
522        match node {
523            Subject::NamedNode(node) => node.into(),
524            Subject::BlankNode(node) => node.into(),
525            #[cfg(feature = "rdf-star")]
526            Subject::Triple(triple) => Self::Triple(triple),
527        }
528    }
529}
530
531impl From<SubjectRef<'_>> for Term {
532    #[inline]
533    fn from(node: SubjectRef<'_>) -> Self {
534        node.into_owned().into()
535    }
536}
537
538impl TryFrom<Term> for NamedNode {
539    type Error = TryFromTermError;
540
541    #[inline]
542    fn try_from(term: Term) -> Result<Self, Self::Error> {
543        if let Term::NamedNode(node) = term {
544            Ok(node)
545        } else {
546            Err(TryFromTermError {
547                term,
548                target: "NamedNode",
549            })
550        }
551    }
552}
553
554impl TryFrom<Term> for BlankNode {
555    type Error = TryFromTermError;
556
557    #[inline]
558    fn try_from(term: Term) -> Result<Self, Self::Error> {
559        if let Term::BlankNode(node) = term {
560            Ok(node)
561        } else {
562            Err(TryFromTermError {
563                term,
564                target: "BlankNode",
565            })
566        }
567    }
568}
569
570impl TryFrom<Term> for Literal {
571    type Error = TryFromTermError;
572
573    #[inline]
574    fn try_from(term: Term) -> Result<Self, Self::Error> {
575        if let Term::Literal(node) = term {
576            Ok(node)
577        } else {
578            Err(TryFromTermError {
579                term,
580                target: "Literal",
581            })
582        }
583    }
584}
585
586impl TryFrom<Term> for Subject {
587    type Error = TryFromTermError;
588
589    #[inline]
590    fn try_from(term: Term) -> Result<Self, Self::Error> {
591        match term {
592            Term::NamedNode(term) => Ok(Self::NamedNode(term)),
593            Term::BlankNode(term) => Ok(Self::BlankNode(term)),
594            #[cfg(feature = "rdf-star")]
595            Term::Triple(term) => Ok(Self::Triple(term)),
596            Term::Literal(_) => Err(TryFromTermError {
597                term,
598                target: "Subject",
599            }),
600        }
601    }
602}
603
604/// A borrowed RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term)
605///
606/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) and [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) (if the `rdf-star` feature is enabled).
607#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
608pub enum TermRef<'a> {
609    NamedNode(NamedNodeRef<'a>),
610    BlankNode(BlankNodeRef<'a>),
611    Literal(LiteralRef<'a>),
612    #[cfg(feature = "rdf-star")]
613    Triple(&'a Triple),
614}
615
616impl TermRef<'_> {
617    #[inline]
618    pub fn is_named_node(&self) -> bool {
619        matches!(self, Self::NamedNode(_))
620    }
621
622    #[inline]
623    pub fn is_blank_node(&self) -> bool {
624        matches!(self, Self::BlankNode(_))
625    }
626
627    #[inline]
628    pub fn is_literal(&self) -> bool {
629        matches!(self, Self::Literal(_))
630    }
631
632    #[cfg(feature = "rdf-star")]
633    #[inline]
634    pub fn is_triple(&self) -> bool {
635        matches!(self, Self::Triple(_))
636    }
637
638    #[inline]
639    pub fn into_owned(self) -> Term {
640        match self {
641            Self::NamedNode(node) => Term::NamedNode(node.into_owned()),
642            Self::BlankNode(node) => Term::BlankNode(node.into_owned()),
643            Self::Literal(literal) => Term::Literal(literal.into_owned()),
644            #[cfg(feature = "rdf-star")]
645            Self::Triple(triple) => Term::Triple(Box::new(triple.clone())),
646        }
647    }
648}
649
650impl fmt::Display for TermRef<'_> {
651    #[inline]
652    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653        match self {
654            Self::NamedNode(node) => node.fmt(f),
655            Self::BlankNode(node) => node.fmt(f),
656            Self::Literal(literal) => literal.fmt(f),
657            #[cfg(feature = "rdf-star")]
658            Self::Triple(triple) => {
659                write!(f, "<<{triple}>>")
660            }
661        }
662    }
663}
664
665impl<'a> From<NamedNodeRef<'a>> for TermRef<'a> {
666    #[inline]
667    fn from(node: NamedNodeRef<'a>) -> Self {
668        Self::NamedNode(node)
669    }
670}
671
672impl<'a> From<&'a NamedNode> for TermRef<'a> {
673    #[inline]
674    fn from(node: &'a NamedNode) -> Self {
675        node.as_ref().into()
676    }
677}
678
679impl<'a> From<BlankNodeRef<'a>> for TermRef<'a> {
680    #[inline]
681    fn from(node: BlankNodeRef<'a>) -> Self {
682        Self::BlankNode(node)
683    }
684}
685
686impl<'a> From<&'a BlankNode> for TermRef<'a> {
687    #[inline]
688    fn from(node: &'a BlankNode) -> Self {
689        node.as_ref().into()
690    }
691}
692
693impl<'a> From<LiteralRef<'a>> for TermRef<'a> {
694    #[inline]
695    fn from(literal: LiteralRef<'a>) -> Self {
696        Self::Literal(literal)
697    }
698}
699
700impl<'a> From<&'a Literal> for TermRef<'a> {
701    #[inline]
702    fn from(literal: &'a Literal) -> Self {
703        literal.as_ref().into()
704    }
705}
706
707#[cfg(feature = "rdf-star")]
708impl<'a> From<&'a Triple> for TermRef<'a> {
709    #[inline]
710    fn from(node: &'a Triple) -> Self {
711        Self::Triple(node)
712    }
713}
714
715impl<'a> From<NamedOrBlankNodeRef<'a>> for TermRef<'a> {
716    #[inline]
717    fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
718        match node {
719            NamedOrBlankNodeRef::NamedNode(node) => node.into(),
720            NamedOrBlankNodeRef::BlankNode(node) => node.into(),
721        }
722    }
723}
724
725impl<'a> From<&'a NamedOrBlankNode> for TermRef<'a> {
726    #[inline]
727    fn from(node: &'a NamedOrBlankNode) -> Self {
728        node.as_ref().into()
729    }
730}
731
732impl<'a> From<SubjectRef<'a>> for TermRef<'a> {
733    #[inline]
734    fn from(node: SubjectRef<'a>) -> Self {
735        match node {
736            SubjectRef::NamedNode(node) => node.into(),
737            SubjectRef::BlankNode(node) => node.into(),
738            #[cfg(feature = "rdf-star")]
739            SubjectRef::Triple(triple) => triple.into(),
740        }
741    }
742}
743
744impl<'a> From<&'a Subject> for TermRef<'a> {
745    #[inline]
746    fn from(node: &'a Subject) -> Self {
747        node.as_ref().into()
748    }
749}
750
751impl<'a> From<&'a Term> for TermRef<'a> {
752    #[inline]
753    fn from(node: &'a Term) -> Self {
754        node.as_ref()
755    }
756}
757
758impl<'a> From<TermRef<'a>> for Term {
759    #[inline]
760    fn from(node: TermRef<'a>) -> Self {
761        node.into_owned()
762    }
763}
764
765/// An owned [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
766///
767/// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation:
768/// ```
769/// use oxrdf::{NamedNode, Triple};
770///
771/// assert_eq!(
772///     "<http://example.com/s> <http://example.com/p> <http://example.com/o>",
773///     Triple {
774///         subject: NamedNode::new("http://example.com/s")?.into(),
775///         predicate: NamedNode::new("http://example.com/p")?,
776///         object: NamedNode::new("http://example.com/o")?.into(),
777///     }
778///     .to_string()
779/// );
780/// # Result::<_,oxrdf::IriParseError>::Ok(())
781/// ```
782#[derive(Eq, PartialEq, Debug, Clone, Hash)]
783pub struct Triple {
784    /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple.
785    pub subject: Subject,
786
787    /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple.
788    pub predicate: NamedNode,
789
790    /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple.
791    pub object: Term,
792}
793
794impl Triple {
795    /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
796    #[inline]
797    pub fn new(
798        subject: impl Into<Subject>,
799        predicate: impl Into<NamedNode>,
800        object: impl Into<Term>,
801    ) -> Self {
802        Self {
803            subject: subject.into(),
804            predicate: predicate.into(),
805            object: object.into(),
806        }
807    }
808
809    /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) from [`Term`]s.
810    ///
811    /// Returns a [`TryFromTermError`] error if the generated triple would be ill-formed.
812    #[inline]
813    pub fn from_terms(
814        subject: impl Into<Term>,
815        predicate: impl Into<Term>,
816        object: impl Into<Term>,
817    ) -> Result<Self, TryFromTermError> {
818        Ok(Self {
819            subject: subject.into().try_into()?,
820            predicate: predicate.into().try_into()?,
821            object: object.into(),
822        })
823    }
824
825    /// Encodes that this triple is in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
826    #[inline]
827    pub fn in_graph(self, graph_name: impl Into<GraphName>) -> Quad {
828        Quad {
829            subject: self.subject,
830            predicate: self.predicate,
831            object: self.object,
832            graph_name: graph_name.into(),
833        }
834    }
835
836    #[inline]
837    pub fn as_ref(&self) -> TripleRef<'_> {
838        TripleRef {
839            subject: self.subject.as_ref(),
840            predicate: self.predicate.as_ref(),
841            object: self.object.as_ref(),
842        }
843    }
844}
845
846impl fmt::Display for Triple {
847    #[inline]
848    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849        self.as_ref().fmt(f)
850    }
851}
852
853/// A borrowed [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
854///
855/// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation:
856/// ```
857/// use oxrdf::{NamedNodeRef, TripleRef};
858///
859/// assert_eq!(
860///     "<http://example.com/s> <http://example.com/p> <http://example.com/o>",
861///     TripleRef {
862///         subject: NamedNodeRef::new("http://example.com/s")?.into(),
863///         predicate: NamedNodeRef::new("http://example.com/p")?,
864///         object: NamedNodeRef::new("http://example.com/o")?.into(),
865///     }
866///     .to_string()
867/// );
868/// # Result::<_,oxrdf::IriParseError>::Ok(())
869/// ```
870
871#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
872pub struct TripleRef<'a> {
873    /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple.
874    pub subject: SubjectRef<'a>,
875
876    /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple.
877    pub predicate: NamedNodeRef<'a>,
878
879    /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple.
880    pub object: TermRef<'a>,
881}
882
883impl<'a> TripleRef<'a> {
884    /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
885    #[inline]
886    pub fn new(
887        subject: impl Into<SubjectRef<'a>>,
888        predicate: impl Into<NamedNodeRef<'a>>,
889        object: impl Into<TermRef<'a>>,
890    ) -> Self {
891        Self {
892            subject: subject.into(),
893            predicate: predicate.into(),
894            object: object.into(),
895        }
896    }
897
898    /// Encodes that this triple is in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
899    #[inline]
900    pub fn in_graph(self, graph_name: impl Into<GraphNameRef<'a>>) -> QuadRef<'a> {
901        QuadRef {
902            subject: self.subject,
903            predicate: self.predicate,
904            object: self.object,
905            graph_name: graph_name.into(),
906        }
907    }
908
909    #[inline]
910    pub fn into_owned(self) -> Triple {
911        Triple {
912            subject: self.subject.into_owned(),
913            predicate: self.predicate.into_owned(),
914            object: self.object.into_owned(),
915        }
916    }
917}
918
919impl fmt::Display for TripleRef<'_> {
920    #[inline]
921    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
922        write!(f, "{} {} {}", self.subject, self.predicate, self.object)
923    }
924}
925
926impl<'a> From<&'a Triple> for TripleRef<'a> {
927    #[inline]
928    fn from(triple: &'a Triple) -> Self {
929        triple.as_ref()
930    }
931}
932
933impl<'a> From<TripleRef<'a>> for Triple {
934    #[inline]
935    fn from(triple: TripleRef<'a>) -> Self {
936        triple.into_owned()
937    }
938}
939
940/// An owned graph name
941///
942/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
943#[derive(Eq, PartialEq, Debug, Clone, Hash, Default)]
944pub enum GraphName {
945    NamedNode(NamedNode),
946    BlankNode(BlankNode),
947    #[default]
948    DefaultGraph,
949}
950
951impl GraphName {
952    #[inline]
953    pub fn is_named_node(&self) -> bool {
954        self.as_ref().is_named_node()
955    }
956
957    #[inline]
958    pub fn is_blank_node(&self) -> bool {
959        self.as_ref().is_blank_node()
960    }
961
962    #[inline]
963    pub fn is_default_graph(&self) -> bool {
964        self.as_ref().is_default_graph()
965    }
966
967    #[inline]
968    pub fn as_ref(&self) -> GraphNameRef<'_> {
969        match self {
970            Self::NamedNode(node) => GraphNameRef::NamedNode(node.as_ref()),
971            Self::BlankNode(node) => GraphNameRef::BlankNode(node.as_ref()),
972            Self::DefaultGraph => GraphNameRef::DefaultGraph,
973        }
974    }
975}
976
977impl fmt::Display for GraphName {
978    #[inline]
979    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
980        self.as_ref().fmt(f)
981    }
982}
983
984impl From<NamedNode> for GraphName {
985    #[inline]
986    fn from(node: NamedNode) -> Self {
987        Self::NamedNode(node)
988    }
989}
990
991impl From<NamedNodeRef<'_>> for GraphName {
992    #[inline]
993    fn from(node: NamedNodeRef<'_>) -> Self {
994        node.into_owned().into()
995    }
996}
997
998impl From<BlankNode> for GraphName {
999    #[inline]
1000    fn from(node: BlankNode) -> Self {
1001        Self::BlankNode(node)
1002    }
1003}
1004
1005impl From<BlankNodeRef<'_>> for GraphName {
1006    #[inline]
1007    fn from(node: BlankNodeRef<'_>) -> Self {
1008        node.into_owned().into()
1009    }
1010}
1011
1012impl From<NamedOrBlankNode> for GraphName {
1013    #[inline]
1014    fn from(node: NamedOrBlankNode) -> Self {
1015        match node {
1016            NamedOrBlankNode::NamedNode(node) => node.into(),
1017            NamedOrBlankNode::BlankNode(node) => node.into(),
1018        }
1019    }
1020}
1021
1022impl From<NamedOrBlankNodeRef<'_>> for GraphName {
1023    #[inline]
1024    fn from(node: NamedOrBlankNodeRef<'_>) -> Self {
1025        node.into_owned().into()
1026    }
1027}
1028
1029/// A borrowed graph name
1030///
1031/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
1032#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash, Default)]
1033pub enum GraphNameRef<'a> {
1034    NamedNode(NamedNodeRef<'a>),
1035    BlankNode(BlankNodeRef<'a>),
1036    #[default]
1037    DefaultGraph,
1038}
1039
1040impl GraphNameRef<'_> {
1041    #[inline]
1042    pub fn is_named_node(&self) -> bool {
1043        matches!(self, Self::NamedNode(_))
1044    }
1045
1046    #[inline]
1047    pub fn is_blank_node(&self) -> bool {
1048        matches!(self, Self::BlankNode(_))
1049    }
1050
1051    #[inline]
1052    pub fn is_default_graph(&self) -> bool {
1053        matches!(self, Self::DefaultGraph)
1054    }
1055
1056    #[inline]
1057    pub fn into_owned(self) -> GraphName {
1058        match self {
1059            Self::NamedNode(node) => GraphName::NamedNode(node.into_owned()),
1060            Self::BlankNode(node) => GraphName::BlankNode(node.into_owned()),
1061            Self::DefaultGraph => GraphName::DefaultGraph,
1062        }
1063    }
1064}
1065
1066impl fmt::Display for GraphNameRef<'_> {
1067    #[inline]
1068    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1069        match self {
1070            Self::NamedNode(node) => node.fmt(f),
1071            Self::BlankNode(node) => node.fmt(f),
1072            Self::DefaultGraph => f.write_str("DEFAULT"),
1073        }
1074    }
1075}
1076
1077impl<'a> From<NamedNodeRef<'a>> for GraphNameRef<'a> {
1078    #[inline]
1079    fn from(node: NamedNodeRef<'a>) -> Self {
1080        Self::NamedNode(node)
1081    }
1082}
1083
1084impl<'a> From<&'a NamedNode> for GraphNameRef<'a> {
1085    #[inline]
1086    fn from(node: &'a NamedNode) -> Self {
1087        node.as_ref().into()
1088    }
1089}
1090
1091impl<'a> From<BlankNodeRef<'a>> for GraphNameRef<'a> {
1092    #[inline]
1093    fn from(node: BlankNodeRef<'a>) -> Self {
1094        Self::BlankNode(node)
1095    }
1096}
1097
1098impl<'a> From<&'a BlankNode> for GraphNameRef<'a> {
1099    #[inline]
1100    fn from(node: &'a BlankNode) -> Self {
1101        node.as_ref().into()
1102    }
1103}
1104
1105impl<'a> From<NamedOrBlankNodeRef<'a>> for GraphNameRef<'a> {
1106    #[inline]
1107    fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
1108        match node {
1109            NamedOrBlankNodeRef::NamedNode(node) => node.into(),
1110            NamedOrBlankNodeRef::BlankNode(node) => node.into(),
1111        }
1112    }
1113}
1114
1115impl<'a> From<&'a NamedOrBlankNode> for GraphNameRef<'a> {
1116    #[inline]
1117    fn from(node: &'a NamedOrBlankNode) -> Self {
1118        node.as_ref().into()
1119    }
1120}
1121
1122impl<'a> From<&'a GraphName> for GraphNameRef<'a> {
1123    #[inline]
1124    fn from(node: &'a GraphName) -> Self {
1125        node.as_ref()
1126    }
1127}
1128
1129impl<'a> From<GraphNameRef<'a>> for GraphName {
1130    #[inline]
1131    fn from(node: GraphNameRef<'a>) -> Self {
1132        node.into_owned()
1133    }
1134}
1135
1136/// An owned [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
1137///
1138/// The default string formatter is returning an N-Quads compatible representation:
1139/// ```
1140/// use oxrdf::{Quad, NamedNode};
1141///
1142/// assert_eq!(
1143///     "<http://example.com/s> <http://example.com/p> <http://example.com/o> <http://example.com/g>",
1144///     Quad {
1145///         subject: NamedNode::new("http://example.com/s")?.into(),
1146///         predicate: NamedNode::new("http://example.com/p")?,
1147///         object: NamedNode::new("http://example.com/o")?.into(),
1148///         graph_name: NamedNode::new("http://example.com/g")?.into(),
1149///     }.to_string()
1150/// );
1151/// # Result::<_,oxrdf::IriParseError>::Ok(())
1152/// ```
1153#[derive(Eq, PartialEq, Debug, Clone, Hash)]
1154pub struct Quad {
1155    /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple.
1156    pub subject: Subject,
1157
1158    /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple.
1159    pub predicate: NamedNode,
1160
1161    /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple.
1162    pub object: Term,
1163
1164    /// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is.
1165    pub graph_name: GraphName,
1166}
1167
1168impl Quad {
1169    /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
1170    #[inline]
1171    pub fn new(
1172        subject: impl Into<Subject>,
1173        predicate: impl Into<NamedNode>,
1174        object: impl Into<Term>,
1175        graph_name: impl Into<GraphName>,
1176    ) -> Self {
1177        Self {
1178            subject: subject.into(),
1179            predicate: predicate.into(),
1180            object: object.into(),
1181            graph_name: graph_name.into(),
1182        }
1183    }
1184
1185    #[inline]
1186    pub fn as_ref(&self) -> QuadRef<'_> {
1187        QuadRef {
1188            subject: self.subject.as_ref(),
1189            predicate: self.predicate.as_ref(),
1190            object: self.object.as_ref(),
1191            graph_name: self.graph_name.as_ref(),
1192        }
1193    }
1194}
1195
1196impl fmt::Display for Quad {
1197    #[inline]
1198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1199        self.as_ref().fmt(f)
1200    }
1201}
1202
1203impl From<Quad> for Triple {
1204    #[inline]
1205    fn from(quad: Quad) -> Self {
1206        Self {
1207            subject: quad.subject,
1208            predicate: quad.predicate,
1209            object: quad.object,
1210        }
1211    }
1212}
1213
1214/// A borrowed [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
1215///
1216/// The default string formatter is returning an N-Quads compatible representation:
1217/// ```
1218/// use oxrdf::{QuadRef, NamedNodeRef};
1219///
1220/// assert_eq!(
1221///     "<http://example.com/s> <http://example.com/p> <http://example.com/o> <http://example.com/g>",
1222///     QuadRef {
1223///         subject: NamedNodeRef::new("http://example.com/s")?.into(),
1224///         predicate: NamedNodeRef::new("http://example.com/p")?,
1225///         object: NamedNodeRef::new("http://example.com/o")?.into(),
1226///         graph_name: NamedNodeRef::new("http://example.com/g")?.into(),
1227///     }.to_string()
1228/// );
1229/// # Result::<_,oxrdf::IriParseError>::Ok(())
1230/// ```
1231#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
1232pub struct QuadRef<'a> {
1233    /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple.
1234    pub subject: SubjectRef<'a>,
1235
1236    /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple.
1237    pub predicate: NamedNodeRef<'a>,
1238
1239    /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple.
1240    pub object: TermRef<'a>,
1241
1242    /// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is.
1243    pub graph_name: GraphNameRef<'a>,
1244}
1245
1246impl<'a> QuadRef<'a> {
1247    /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
1248    #[inline]
1249    pub fn new(
1250        subject: impl Into<SubjectRef<'a>>,
1251        predicate: impl Into<NamedNodeRef<'a>>,
1252        object: impl Into<TermRef<'a>>,
1253        graph_name: impl Into<GraphNameRef<'a>>,
1254    ) -> Self {
1255        Self {
1256            subject: subject.into(),
1257            predicate: predicate.into(),
1258            object: object.into(),
1259            graph_name: graph_name.into(),
1260        }
1261    }
1262
1263    #[inline]
1264    pub fn into_owned(self) -> Quad {
1265        Quad {
1266            subject: self.subject.into_owned(),
1267            predicate: self.predicate.into_owned(),
1268            object: self.object.into_owned(),
1269            graph_name: self.graph_name.into_owned(),
1270        }
1271    }
1272}
1273
1274impl fmt::Display for QuadRef<'_> {
1275    #[inline]
1276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1277        if self.graph_name.is_default_graph() {
1278            write!(f, "{} {} {}", self.subject, self.predicate, self.object)
1279        } else {
1280            write!(
1281                f,
1282                "{} {} {} {}",
1283                self.subject, self.predicate, self.object, self.graph_name
1284            )
1285        }
1286    }
1287}
1288
1289impl<'a> From<QuadRef<'a>> for TripleRef<'a> {
1290    #[inline]
1291    fn from(quad: QuadRef<'a>) -> Self {
1292        Self {
1293            subject: quad.subject,
1294            predicate: quad.predicate,
1295            object: quad.object,
1296        }
1297    }
1298}
1299
1300impl<'a> From<&'a Quad> for QuadRef<'a> {
1301    #[inline]
1302    fn from(quad: &'a Quad) -> Self {
1303        quad.as_ref()
1304    }
1305}
1306
1307impl<'a> From<QuadRef<'a>> for Quad {
1308    #[inline]
1309    fn from(quad: QuadRef<'a>) -> Self {
1310        quad.into_owned()
1311    }
1312}
1313
1314/// An error return by some [`TryFrom<Term>`](TryFrom)  implementations.
1315#[derive(Debug, Clone, thiserror::Error)]
1316#[error("{term} can not be converted to a {target}")]
1317pub struct TryFromTermError {
1318    term: Term,
1319    target: &'static str,
1320}
1321
1322impl TryFromTermError {
1323    /// The term that can't be converted
1324    #[inline]
1325    pub fn into_term(self) -> Term {
1326        self.term
1327    }
1328}
1329
1330#[cfg(test)]
1331#[allow(clippy::panic_in_result_fn)]
1332mod tests {
1333    use super::*;
1334
1335    #[test]
1336    fn triple_from_terms() -> Result<(), TryFromTermError> {
1337        assert_eq!(
1338            Triple::from_terms(
1339                NamedNode::new_unchecked("http://example.com/s"),
1340                NamedNode::new_unchecked("http://example.com/p"),
1341                NamedNode::new_unchecked("http://example.com/o"),
1342            )?,
1343            Triple::new(
1344                NamedNode::new_unchecked("http://example.com/s"),
1345                NamedNode::new_unchecked("http://example.com/p"),
1346                NamedNode::new_unchecked("http://example.com/o"),
1347            )
1348        );
1349        assert_eq!(
1350            Triple::from_terms(
1351                Literal::new_simple_literal("foo"),
1352                NamedNode::new_unchecked("http://example.com/p"),
1353                NamedNode::new_unchecked("http://example.com/o"),
1354            )
1355            .unwrap_err()
1356            .into_term(),
1357            Term::from(Literal::new_simple_literal("foo"))
1358        );
1359        assert_eq!(
1360            Triple::from_terms(
1361                NamedNode::new_unchecked("http://example.com/s"),
1362                Literal::new_simple_literal("foo"),
1363                NamedNode::new_unchecked("http://example.com/o"),
1364            )
1365            .unwrap_err()
1366            .into_term(),
1367            Term::from(Literal::new_simple_literal("foo"))
1368        );
1369        Ok(())
1370    }
1371}