Skip to main content

oxrdf/
triple.rs

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