rdf_dynsyn/parser/triples/
sync.rs1use std::io::BufRead;
2
3use sophia_api::prelude::{Iri, TripleParser};
4use sophia_turtle::parser::{nt::NTriplesParser, turtle::TurtleParser};
5#[cfg(feature = "rdf_xml")]
6use sophia_xml::parser::RdfXmlParser;
7
8use super::{factory::DynSynTripleParserFactory, source::DynSynTripleSource};
9use crate::syntax::{self, invariant::triples_parsable::TriplesParsableSyntax};
10
11#[derive(Debug, Clone)]
13pub enum InnerTripleParser {
14 NTriples(NTriplesParser),
15 Turtle(TurtleParser),
16 #[cfg(feature = "rdf_xml")]
17 RdfXml(RdfXmlParser),
18}
19
20impl From<NTriplesParser> for InnerTripleParser {
21 #[inline]
22 fn from(p: NTriplesParser) -> Self {
23 Self::NTriples(p)
24 }
25}
26
27impl From<TurtleParser> for InnerTripleParser {
28 #[inline]
29 fn from(p: TurtleParser) -> Self {
30 Self::Turtle(p)
31 }
32}
33
34#[cfg(feature = "rdf_xml")]
35impl From<RdfXmlParser> for InnerTripleParser {
36 #[inline]
37 fn from(p: RdfXmlParser) -> Self {
38 Self::RdfXml(p)
39 }
40}
41
42impl InnerTripleParser {
43 pub fn new(syntax_: TriplesParsableSyntax, base_iri: Option<Iri<String>>) -> Self {
45 match syntax_.into_subject() {
46 syntax::N_TRIPLES => NTriplesParser {}.into(),
47 syntax::TURTLE => TurtleParser { base: base_iri }.into(),
48 #[cfg(feature = "rdf_xml")]
49 syntax::RDF_XML => RdfXmlParser { base: base_iri }.into(),
50 _ => unreachable!(),
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
68pub struct DynSynTripleParser(InnerTripleParser);
69
70impl DynSynTripleParser {
71 #[inline]
73 pub fn new(syntax_: TriplesParsableSyntax, base_iri: Option<Iri<String>>) -> Self {
74 Self(InnerTripleParser::new(syntax_, base_iri))
75 }
76}
77
78impl<R> TripleParser<R> for DynSynTripleParser
79where
80 R: BufRead,
81{
82 type Source = DynSynTripleSource<R>;
83
84 fn parse(&self, data: R) -> Self::Source {
85 match &self.0 {
86 InnerTripleParser::NTriples(p) => DynSynTripleSource(p.parse(data).into()),
87 InnerTripleParser::Turtle(p) => DynSynTripleSource(p.parse(data).into()),
88 #[cfg(feature = "rdf_xml")]
89 InnerTripleParser::RdfXml(p) => DynSynTripleSource(p.parse(data).into()),
90 }
91 }
92}
93
94impl DynSynTripleParserFactory {
95 #[inline]
98 pub fn new_parser(
99 &self,
100 syntax_: TriplesParsableSyntax,
101 base_iri: Option<Iri<String>>,
102 ) -> DynSynTripleParser {
103 DynSynTripleParser::new(syntax_, base_iri)
104 }
105}
106
107#[cfg(test)]
112mod tests {
113 use std::collections::HashSet;
114
115 use once_cell::sync::Lazy;
116 use sophia_api::{
117 parser::{IntoParsable, TripleParser},
118 source::TripleSource,
119 term::SimpleTerm,
120 };
121 use sophia_isomorphism::isomorphic_graphs;
122 use sophia_turtle::parser::{nt::NTriplesParser, turtle::TurtleParser};
123
124 use super::*;
125 use crate::{
126 parser::test_data::*,
127 syntax::invariant::triples_parsable::{TP_N_TRIPLES, TP_RDF_XML, TP_TURTLE},
128 tests::TRACING,
129 };
130
131 static DYNSYN_TRIPLE_PARSER_FACTORY: Lazy<DynSynTripleParserFactory> =
132 Lazy::new(DynSynTripleParserFactory::default);
133
134 fn check_graph_parse_isomorphism<'b, B, P1, P2>(p1: &P1, p2: &P2, qs: &'b str)
135 where
136 P1: TripleParser<B>,
137 P2: TripleParser<B>,
138 &'b str: IntoParsable<Target = B>,
139 {
140 let mut g1 = HashSet::<[SimpleTerm; 3]>::new();
141 p1.parse_str(qs).add_to_graph(&mut g1).unwrap();
142
143 let mut g2 = HashSet::<[SimpleTerm; 3]>::new();
144 p2.parse_str(qs).add_to_graph(&mut g2).unwrap();
145
146 assert!(isomorphic_graphs(&g1, &g2).unwrap());
147 }
148
149 #[test]
150 pub fn correctly_parses_turtle() {
151 Lazy::force(&TRACING);
152 check_graph_parse_isomorphism(
153 &TurtleParser {
154 base: Some(BASE_IRI1.clone()),
155 },
156 &DYNSYN_TRIPLE_PARSER_FACTORY.new_parser(TP_TURTLE, Some(BASE_IRI1.clone())),
157 GRAPH_STR_TURTLE,
158 );
159 }
160
161 #[test]
162 pub fn correctly_parses_ntriples() {
163 Lazy::force(&TRACING);
164 check_graph_parse_isomorphism(
165 &NTriplesParser {},
166 &DYNSYN_TRIPLE_PARSER_FACTORY.new_parser(TP_N_TRIPLES, Some(BASE_IRI1.clone())),
167 GRAPH_STR_N_TRIPLES,
168 );
169 }
170
171 #[cfg(feature = "rdf_xml")]
172 #[test]
173 pub fn correctly_parses_rdf_xml() {
174 Lazy::force(&TRACING);
175 check_graph_parse_isomorphism(
176 &RdfXmlParser {
177 base: Some(BASE_IRI1.clone()),
178 },
179 &DYNSYN_TRIPLE_PARSER_FACTORY.new_parser(TP_RDF_XML, Some(BASE_IRI1.clone())),
180 GRAPH_STR_RDF_XML,
181 );
182 }
183}